i18next 1.0.1

i18next 1.0.1

测试已测试
语言语言 Obj-CObjective C
许可 MIT
发布最新发布2015年9月

Jean Regisser 维护。



i18next 1.0.1

  • Jean Regisser

i18next-ios

i18next-ios 是 i18next 的原生 iOS 版本。

为什么?

为了在 Web、Android 和 iOS 上使用相同的翻译字符串,我们决定使用 i18next 的功能和数据格式。

这个库是我们为 iOS 实现的实现。我们已经在生产中使用它几年了。

特性

  • [x] 支持变量
  • [x] 支持嵌套
  • [x] 支持上下文
  • [x] 支持多个复数形式
  • [x] Gettext 支持
  • [x] Sprintf 支持
  • [ ] 检测语言
  • [x] 优雅的翻译查找
  • [x] 获取字符串或对象树
  • [x] 从服务器获取资源文件
  • [x] 资源缓存
  • [ ] 将缺少的资源发布到服务器
  • [x] 高度可配置
  • [ ] 自定义后处理
  • [x] 完备的单元测试覆盖率

要求

  • iOS 7.0+
  • Xcode 6.4

通讯

  • 如果您 发现了一个错误,请打开一个问题。
  • 如果您 有一个功能请求,请打开一个问题。
  • 如果您 想做出贡献,请提交一个 pull 请求。

用法

初始化

实例

创建一个新的实例

I18Next *i18n = [[I18Next alloc] init];

或获取一个共享实例

I18Next *i18n = [I18Next sharedInstance];

如果您使用共享实例,您可以使用方便的 I18NEXT 助手宏来获取已翻译的值。

资源加载

基本选项

设置语言
I18NextOptions* options = [I18NextOptions new];
options.lang = @"en-US";

资源将按以下顺序解析

  1. 尝试使用语言代号加国家代号,例如,'en-US'
  2. 其次在仅语言代号中查找,例如,'en'
  3. 最后在定义的回退语言中查找,默认:'dev'
附加命名空间
I18NextOptions* options = [I18NextOptions new];
options.namespace = @"myNamespace";
// or multiple
options.namespaces = @[ @"myNamespace1", @"myNamespace2" ];

将加载附加命名空间。

使用options.defaultNamespace = @"myNamespace"指定默认命名空间。

取消/设置回退语言
I18NextOptions* options = [I18NextOptions new];
options.fallbackLang = @"en";

如果没有设置,它将默认为'dev'。如果开启,所有缺失的键/值将会发送到该语言。

生产提示:将回退语言设置为有意义的语言,例如'en'。

关闭回退语言特性
options.fallbackLang = nil;

因为回退Lang默认为'dev',您可以通过将选项值设置为nil来关闭它。这将防止加载回退资源文件以及查找回退文件内部的任何缺失值。

取消/设置回退命名空间
使用默认命名空间
// given resourcesfile namespace1.en.json (default ns)
{ 
   key1: 'value of key 1' 
}

// given additional resourcesfile namespace2.en.json
{ 
  keys: { 
    2: 'value of key 2',
    3: 'value of key 3'
  }
}
options.fallbackToDefaultNamespace = YES;
...
I18NEXT(@"namespace2:key1"); // -> value of key 1
使用一个或多个命名空间
// given resourcesfile namespace1.en.json
{ 
   key1: 'value of key 1 - ns1' 
}

// given resourcesfile namespace2.en.json
{ 
   key1: 'value of key 1 - ns2' 
   key2: 'value of key 2 - ns2' 
}

// given resourcesfile namespace3.en.json
{ 
  keys: { 
    2: 'value of key 2',
    3: 'value of key 3'
  }
}
options.fallbackNamespace = @"namespace2";
...
I18NEXT("namespace3:key1"); // -> value of key 1 - ns2
// array
options.fallbackNamespaces = @[ @"namespace1", @"namespace2" ]; // order matters
...
I18NEXT("namespace3:key1"); // -> value of key 1 - ns1
I18NEXT("namespace3:key2"); // -> value of key 2 - ns2

如果资源在命名空间中找不到,将查找默认命名空间。默认情况下,此选项是关闭的。

指定要加载的区域设置
仅加载当前资源文件
I18NextOptions* options = [I18NextOptions new];
options.langLoadType = I18NextLangLoadTypeCurrent;

如果langLoadType选项设置为current,i18next将加载当前设置的语言(这可能是一个特定语言(en-US)或非特定语言(en)资源文件)。

提示:要防止加载fallbackLang的资源文件,将fallbackLang设置为nil

仅加载非特定资源文件
I18NextOptions* options = [I18NextOptions new];
options.langLoadType = I18NextLangLoadTypeUnspecific;

如果设置为非特定,i18next将始终加载非特定资源文件(例如,en而不是en-US)。

提示:要防止加载fallbackLang的资源文件,将fallbackLang设置为nil

处理空值
// given resourcesfile namespace1.dev.json (fallback lang)
{ 
   key1: 'fallback' 
}
// given resourcesfile namespace1.en.json
{ 
   key1: null 
}
options.fallbackOnNull = YES;
...
I18NEXT("key1"); // -> 'fallback'

options.fallbackOnNull = NO;
...
I18NEXT("key1"); // -> ''

默认是YES。

处理空字符串值
// given resourcesfile namespace1.dev.json (fallback lang)
{ 
   key1: 'fallback' 
}
// given resourcesfile namespace1.en.json
{ 
   key1: '' 
}

此功能在iOS库中没有实现

加载资源选项

传递资源存储
I18NextOptions* options = [I18NextOptions new];

// tree: lng -> namespace -> key -> nested key
options.resourcesStore = @{
  @"dev": @{ @"translation": @{ @"key": @"value" } },
  @"en": @{ @"translation": @{ @"key": @"value" } },
  @"en-US": @{ @"translation": @{ @"key": @"value" } },
};

[i18n loadWithOptions:[options asDictionary] completion:^(NSError *error) {
    // new resources are successfully loaded if error == nil
}];

当您提供资源时,完成块将立即触发,不会加载任何外部资源!

设置静态路由以从其加载资源
I18NextOptions* options = [I18NextOptions new];

options.resourcesBaseURL = [NSURL URLWithString:@"http://example.com"];
options.resourcesGetPathTemplate = @"locales/__lng__/__ns__.json";

[i18n loadWithOptions:[options asDictionary] completion:^(NSError *error) {
    // new resources are successfully loaded if error == nil
}];

将加载'http://example.com/locales/en-US/translation.json'。

如果语言设置为'en-US',以下资源文件将逐个加载

  • en-US
  • en
  • dev(默认回退语言)

提示

  • 为保持获取的资源在本地缓存中,设置选项updateLocalCache = YES
  • 在请求中将countryCode小写,例如将'cn'设置为'en-US',设置选项lowercaseLang = YES
加载服务器上动态生成的资源
I18NextOptions* options = [I18NextOptions new];

options.resourcesBaseURL = [NSURL URLWithString:@"http://example.com"];
options.resourcesGetPathTemplate = @"resources.json?lng=__lng__&ns=__ns__";
options.dynamicLoad = YES;

[i18n loadWithOptions:[options asDictionary] completion:^(NSError *error) {
    // new resources are successfully loaded if error == nil
}];

将请求'http://example.com/resources.json?lng=en-US+en+dev&ns=translation'。

如果语言设置为'en-US',以下资源将在一个请求中加载

  • en-US
  • en
  • dev(默认回退语言)

提示:要保持在本地缓存中的获取的资源,设置选项updateLocalCache = YES

从语言包(lproj目录)加载资源
I18NextOptions* options = [I18NextOptions new];

options.loadFromLanguageBundles = YES;

[i18n loadWithOptions:[options asDictionary] completion:^(NSError *error) {
    // new resources are successfully loaded if error == nil
}];

从应用程序包的lproj文件夹中加载资源:en.lproj/i18next.json

这可以与loadFromLocalCache选项结合使用。在这种情况下,将首先加载本地缓存,只有当缓存为空时才会使用语言包。

提示:若要使用另一个文件名,例如“myFile”,请设置选项filenameInLanguageBundles = @"myFile"

从本地缓存中加载资源
I18NextOptions* options = [I18NextOptions new];

options.loadFromLocalCache = YES;

[i18n loadWithOptions:[options asDictionary] completion:^(NSError *error) {
    // new resources are successfully loaded if error == nil
}];

将从本地缓存中加载资源。

当设置updateLocalCache = YES时,每次从远程服务器加载新资源时,本地缓存都会更新。

提示:若要使用自定义缓存路径,请设置localCachePath选项。

同步本地加载
I18NextOptions* options = [I18NextOptions new];

options.loadFromLanguageBundles = YES;
options.loadFromLocalCache = YES;
options.synchronousLocalLoad = YES;

[i18n loadWithOptions:[options asDictionary] completion:^(NSError *error) {
    // new resources are successfully loaded if error == nil
}];

I18NEXT("key"); // -> "value"

将同步加载本地资源(仅针对语言包或本地缓存)。这对于应用程序初始化很有用,这样下一个调用翻译密钥时可以成功(如果它在语言包或本地缓存中)。

翻译功能

目前并不支持i18next的javascript实现的所有功能。以下是从i18next网站上的列表及其如何使用此库。

访问资源

使用默认命名空间
// given resourcefile translation.en.json
{
  key1: 'value of key 1'
}
I18NEXT(@"key1"); // -> value of key 1
设置命名空间
// given resourcesfile namespace1.en.json (default ns)
{
   key1: 'value of key 1'
}

// given additional resourcesfile namespace2.en.json
{
  keys: {
    2: 'value of key 2',
    3: 'value of key 3'
  }
}
I18NEXT(@"key1"); // -> value of key 1
I18NEXT(@"namespace1.key1"); // -> value of key 1
I18NEXT(@"keys.2"); // -> missing key
I18NEXT(@"namespace2:keys.2"); // -> value of key 2
I18NEXT(@"namespace2:keys.3"); // -> value of key 3
使用多个密钥(找到的第一个将被翻译)
// given resourcefile translation.en.json
{
  key1: 'value of key 1'
}
I18NEXT(@[ @"notExists", @"key1" ]); // -> value of key 1

JSON多行

// given resources in arabic
{
  'en-US': {
    translation: {
      key: [
        "line1",
        "line2",
        "line3"
      ]
    }
  }
};

翻译将与'\n'连接。

JSON中的数组

// given resources in arabic
{
  'en-US': {
    translation: {
      people: [
        { name: "tom" },
        { name: "steve" }
      ]
    }
  }
};

此功能在iOS库中没有实现

提供默认值

// given resources
{
  'en-US': { translation: { // key not found } }
};

如果没有找到则返回默认值

I18NEXT(@"key" defaultValue:@"my text"); // -> my text

嵌套资源

// given resources
{
  dev: { translation: { nesting1: '1 $t(nesting2)' } },
  en: { translation: { nesting2: '2 $t(nesting3)' } },
  'en-US': { translation: {  nesting3: '3' } }
};
I18NEXT(@"nesting1"); // -> 1 2 3

带有replace选项的嵌套资源

// given resources
{
  en: { translation: {
    girlsAndBoys: '$t(girls, {"count": __girls__}) and __count__ boy',
    girlsAndBoys_plural: '$t(girls, {"count": __girls__}) and __count__ boys' },
    girls: '__count__ girl',
    girls_plural: '__count__ girls' } }
};
I18NEXT(@"girlsAndBoys" count:2 variables:@{ @"girls": @"3"}); // -> 3 girls and 2 boys

替换变量

// given resources
{
  'en-US': { translation: {  key: '__myVar__ are important' } }
};
I18NEXT(@"key" variables:@{ @"myVar": @"variables"}); // -> variables are important

Sprintf支持

// given resources
{
  'en-US': { translation: {
    key1: 'The first 4 letters of the english alphabet are: %s, %s, %s and %s'
  }}
};
[[I18Next sharedInstance] tf:@"key1", "a", "b", "c", "d"];

简单复数

// given resources
{
  'en-US': {
    translation: {
      key: '__count__ child',
      key_plural: '__count__ children'
    }
  }
};
I18NEXT(@"key" count:0); // -> 0 children
I18NEXT(@"key" count:1); // -> 1 child
I18NEXT(@"key" count:5); // -> 5 children

不确定复数

// given resources
{
  'en-US': {
    translation: {
      key: '__count__  child',
      key_plural: '__count__  children',
      key_indefinite: 'a child',
      key_plural_indefinite: 'some children'
    }
  }
};

此功能在iOS库中没有实现

多个复数形式

// given resources in arabic
{
  'ar': {
    translation: {
      key: 'singular',
      key_plural_0: 'zero',
      key_plural_2: 'two',
      key_plural_3: 'few',
      key_plural_11: 'many',
      key_plural_100: 'plural'
    }
  }
};
I18NEXT(@"key" count:   0); // -> zero
I18NEXT(@"key" count:   1); // -> singular
I18NEXT(@"key" count:   2); // -> two
I18NEXT(@"key" count:   3); // -> few
I18NEXT(@"key" count:   4); // -> few
I18NEXT(@"key" count: 104); // -> few
I18NEXT(@"key" count:  11); // -> many
I18NEXT(@"key" count:  99); // -> many
I18NEXT(@"key" count: 199); // -> many
I18NEXT(@"key" count: 100); // -> plural

你有什么期望吗? ;)。

提示:i18next为所有语言提供了功能。

使用翻译上下文

// given resources
{
  'en-US': {
    translation: {
      friend: 'A friend',
      friend_male: 'A boyfriend',
      friend_female: 'A girlfriend'
    }
  }
};
I18NEXT(@"friend" count:0); // -> A friend
I18NEXT(@"friend" context:@"male"); // -> A boyfriend
I18NEXT(@"friend" context@"female"); // -> A girlfriend

致谢

i18next及其所有贡献者。