欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net

在这里插入图片描述

前言

全球化应用经常需要处理包含各种重音符号(Accent)和变音符号(Diacritic)的文本,如法语的 “café”、德语的 “München” 或西班牙语的 “mañana”。如果不进行处理,用户在搜索 “cafe” 时可能搜不到 “café”,导致体验极差。

diacritic 是一个专注于解决此类问题的轻量级 Dart 库。它能在几乎不损失语义的情况下,将这些字符转换为其最接近的 ASCII 形式。本文将介绍如何在 OpenHarmony 应用中利用它优化搜索和排序体验。

一、diacritic 简介

1.1 核心功能

  • 移除变音符号:将 à, é, î, ö 等转换为 a, e, i, o
  • 保持语义:尽量寻找视觉或发音相似的替代字符。

1.2 OpenHarmony 适配说明

diacritic 完全用 Dart 编写,无任何平台依赖。它在 OpenHarmony 设备上的运行效果与全平台一致,且性能极快。

用户输入: München

移除变音符

规范化后: Munchen

搜索数据库

命中结果

二、集成与基础用法

2.1 添加依赖

dependencies:
  diacritic: ^0.1.6

2.2 基础转换

import 'package:diacritic/diacritic.dart';

void main() {
  // 1. 简单替换
  print(removeDiacritics('café'));    // 输出: cafe
  print(removeDiacritics('München')); // 输出: Munchen
  print(removeDiacritics('Åland'));   // 输出: Aland
  
  // 2. 混合字符
  print(removeDiacritics('Héllo Wörld!')); // Hello World!
}

三、常见应用场景与示例

3.1 示例一:实现模糊搜索

最常见的场景是做一个忽略重音的搜索功能。

import 'package:diacritic/diacritic.dart';

bool searchMatch(String query, String text) {
  // 将查询词和目标文本都规范化为无变音符号的小写形式
  final normalizedQuery = removeDiacritics(query.toLowerCase());
  final normalizedText = removeDiacritics(text.toLowerCase());
  
  return normalizedText.contains(normalizedQuery);
}

void testSearch() {
  const dataset = ['Sèvres', 'Céline', 'Åland', 'München'];
  const query = 'sev'; // 用户输入 "sev"
  
  final results = dataset.where((item) => searchMatch(query, item)).toList();
  print(results); // [Sèvres]
}

在这里插入图片描述

3.2 示例二:各种语言人名排序

直接对包含特殊字符的字符串列表排序往往不符合用户预期。规范化后再排序通常更自然。

import 'package:diacritic/diacritic.dart';

void sortNames() {
  final names = ['Élodie', 'Ezra', 'Ève', 'Adam'];
  
  // 按照规范化后的字符串排序
  names.sort((a, b) {
    return removeDiacritics(a).compareTo(removeDiacritics(b));
  });
  
  print(names); // [Adam, Élodie, Ève, Ezra] (E开头的名字现在聚合在一起了)
}

在这里插入图片描述

3.3 示例三:生成 URL Slug

将文章标题转换为 URL 友好的格式。

import 'package:diacritic/diacritic.dart';

String generateSlug(String title) {
  // 1. 移除变音符号
  var slug = removeDiacritics(title);
  
  // 2. 转换为小写
  slug = slug.toLowerCase();
  
  // 3. 替换非字母数字字符为连字符
  slug = slug.replaceAll(RegExp(r'[^a-z0-9]'), '-');
  
  // 4. 去除多余连字符
  slug = slug.replaceAll(RegExp(r'-+'), '-').trim();
  
  return slug;
}

void testSlug() {
  print(generateSlug('Café & Crème: A Review')); 
  // 输出: cafe-creme-a-review
}

在这里插入图片描述

四、完整实战示例:国际化城市搜索

本示例展示一个 OpenHarmony 搜索界面。列表包含世界各地的城市名,用户即便输入不带重音的字符也能精准匹配。

4.1 示例代码

import 'package:flutter/material.dart';
import 'package:diacritic/diacritic.dart';

void main() {
  runApp(const MaterialApp(home: CitySearchPage()));
}

class CitySearchPage extends StatefulWidget {
  const CitySearchPage({super.key});

  
  State<CitySearchPage> createState() => _CitySearchPageState();
}

class _CitySearchPageState extends State<CitySearchPage> {
  // 模拟数据源
  final List<String> _allCities = [
    'Zürich',
    'München',
    'São Paulo',
    'Montréal',
    'Bogotá',
    'Curaçao',
    'New York',
    'Paris',
  ];

  List<String> _filteredCities = [];
  final TextEditingController _controller = TextEditingController();

  
  void initState() {
    super.initState();
    _filteredCities = _allCities; // 初始显示全部
    _controller.addListener(_onSearchChanged);
  }

  
  void dispose() {
    _controller.removeListener(_onSearchChanged);
    _controller.dispose();
    super.dispose();
  }

  void _onSearchChanged() {
    final query = _controller.text;
    setState(() {
      if (query.isEmpty) {
        _filteredCities = _allCities;
      } else {
        // 核心过滤逻辑
        _filteredCities = _allCities.where((city) {
          final normalizedCity = removeDiacritics(city).toLowerCase();
          final normalizedQuery = removeDiacritics(query).toLowerCase();
          return normalizedCity.contains(normalizedQuery);
        }).toList();
      }
    });
  }

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Diacritic Search Demo')),
      body: Column(
        children: [
          Padding(
            padding: const EdgeInsets.all(16.0),
            child: TextField(
              controller: _controller,
              decoration: const InputDecoration(
                labelText: '搜索城市 (如 munchen, sao paulo)',
                prefixIcon: Icon(Icons.search),
                border: OutlineInputBorder(),
              ),
            ),
          ),
          Expanded(
            child: ListView.builder(
              itemCount: _filteredCities.length,
              itemBuilder: (context, index) {
                final city = _filteredCities[index];
                return ListTile(
                  leading: const Icon(Icons.location_city),
                  title: Text(city),
                  subtitle: Text('Original: $city -> Normalized: ${removeDiacritics(city)}'),
                );
              },
            ),
          ),
        ],
      ),
    );
  }
}

在这里插入图片描述

五、总结

diacritic 虽然功能单一,但却是提升多语言应用用户体验的利器。在 OpenHarmony 平台上,它无需任何特殊配置即可开箱即用。

最佳实践

  1. 搜索优化:始终在后台对索引和查询词同时应用 removeDiacritics
  2. 数据清洗:在保存用户输入到数据库前,如果主要用于标识用途(如 username slug),建议清理。
  3. 保持原样显示:只在逻辑处理时转换,UI 上仍应展示原始的 München 以尊重用户习惯。
Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐