【问题标题】:How to convert to "combining diacritical marks" on iOS如何在 iOS 上转换为“组合变音符号”
【发布时间】:2016-06-27 09:45:09
【问题描述】:

在我的应用程序中,我有一些字符后跟它们的“修饰符变音标记”(例如“o^”,其中“^”是 unicode 0x02c6),我想将它们转换为完全预先组合的字符(例如“ô” - Unicode 0x00f4)。我尝试使用 NSString 方法 precomposedStringWithCanonicalMapping,但是经过几个小时的头撞墙试图弄清楚它为什么不起作用后,我发现它只会将“组合变音符号”(http://www.unicode.org/charts/PDF/U0300.pdf)转换为预先组合的字符。好的,所以我需要做的就是将我所有的“修饰符变音标记”转换为“组合变音标记”,然后对结果字符串执行 precomposedStringWithCanonicalMapping,我就完成了。这确实有效,但我想知道是否有一种不那么乏味/容易出错的方法来做到这一点?这是我的 NSString 类别方法,似乎可以修复大多数字符-

- (instancetype)combineDiacritics
{
    static NSDictionary<NSNumber *, NSNumber *> *sDiacriticalSubstDict; //unichar of diacritic -> unichar of combining diacritic
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        //http://www.unicode.org/charts/PDF/U0300.pdf
        sDiacriticalSubstDict = @{ @(0x02cb) : @(0x0300), @(0x00b4) : @(0x0301), @(0x02c6) : @(0x0302), @(0x02dc) : @(0x0303), @(0x02c9) : @(0x0304),   //Grave, Acute, Circumflex, Tilde, Macron
                                   @(0x00af) : @(0x0305), @(0x02d8) : @(0x0306), @(0x02d9) : @(0x0307), @(0x00a8) : @(0x0308), @(0x02c0) : @(0x0309),   //Overline, Breve, Dot above, Diaeresis
                                   @(0x00b0) : @(0x030a), @(0x02da) : @(0x030b), @(0x02c7) : @(0x030c), @(0x02c8) : @(0x030d), @(0x02bb) : @(0x0312),   //Ring above, Double Acute, Caron, Vertical line above, Cedilla above
                                   @(0x02bc) : @(0x0313), @(0x02bd) : @(0x0314), @(0x02b2) : @(0x0321), @(0x02d4) : @(0x0323), @(0x02b1) : @(0x0324),   //Comma above, Reversed comma above, Palatalized hook below, Dot below, Diaeresis below
                                   @(0x00b8) : @(0x0327), @(0x02db) : @(0x0328), @(0x02cc) : @(0x0329), @(0x02b7) : @(0x032b), @(0x02cd) : @(0x0331),   //Cedilla, Ogonek, Vert line below, Inverted double arch below, Macron below
                                   };
    });
    NSMutableString* __block buffer = [NSMutableString stringWithCapacity:self.length];
    [self enumerateSubstringsInRange:NSMakeRange(0, self.length) options:NSStringEnumerationByComposedCharacterSequences usingBlock: ^(NSString* substring, NSRange substringRange, NSRange enclosingRange, BOOL* stop) {
                          NSString *newString = nil;
                          if (substring.length == 1)    //The diacriticals are all Unicode BMP.
                          {
                              unichar uniChar = [substring characterAtIndex:0];
                              unichar newUniChar = [sDiacriticalSubstDict[@(uniChar)] integerValue];
                              if (newUniChar != 0)
                              {
                                  NSLog(@"Unichar %04x => %04x", uniChar, newUniChar);
                                  newString = [NSString stringWithCharacters:&newUniChar length:1];
                              }
                          }
                          if (newString)
                              [buffer appendString:newString];
                          else
                              [buffer appendString:substring];
                      }];

    NSString *precomposedStr = [buffer precomposedStringWithCanonicalMapping];
    return precomposedStr;
}

有谁知道进行这种转换的更多内置方法?

【问题讨论】:

    标签: objective-c unicode localization nsstring


    【解决方案1】:

    没有进行这种转换的内置方法,因为间距修饰符字母块 (U+02B0..U+02FF) 中的字符不打算用作变音符号。来自 Unicode 标准的第 7.8 节:

    它们没有正式组合标记(gc=Mn 或 gc=Mc),也没有以图形方式与它们修改的基本字母组合。他们本身就是基础角色。

    变音符号的间隔克隆。一些公司标准明确规定了组合变音符号的间距和非间距形式,Unicode 标准在可行时为这些解释提供了匹配代码。

    如果要将它们转换为组合形式,则需要从 Spacing Modifier Letters code chart 中的交叉引用构建一个表(正如您已经在做的那样)。

    【讨论】:

      猜你喜欢
      • 2018-07-09
      • 1970-01-01
      • 1970-01-01
      • 2018-01-31
      • 2011-05-12
      • 1970-01-01
      • 2019-07-13
      • 1970-01-01
      • 2011-04-18
      相关资源
      最近更新 更多