- 版本:0.4.1
- GitHub: https://github.com/EddyVerbruggen/nativescript-i18n
- NPM: https://npmjs.net.cn/package/nativescript-i18n
- 下载
- 昨天:0
- 上周:0
- 上个月:0
nativescript-i18n
这是一个实现 i18n 的插件,使用起来非常简单。
它使用每个平台的原生功能,无需单独的 JS 或 JSON 文件。
它深受 NativeLang 和 此线程 的启发
插件在应用级别定义了一个 L()
方法,因此可以从 XML 和 JS 文件中访问。
请务必阅读重要部分! :smile
致谢
首先感谢 Dan Tamas (@rborn) 过去开发和维护此插件。当他因为优先级调整而不得不放弃它时,他非常友好地将存储库移给了我。
感谢 @TheBrousse 和 @ValioStoychev 在 iOS 方面的帮助以及 @alejonext 创建初始模块。
还要感谢所有使此存储库变得更好的 贡献者 :)
用法
在您的应用中安装插件
npm install --save nativescript-i18n
在 app
文件夹中创建一个名为 i18n
的文件夹,结构如下
app
|
|-- App_Resources
|
[...]
|
|-- i18n
|
|-- en
|- strings.xml
|
|-- es
|- strings.xml
尽早在 app.js
中引入 nativescript-i18n
和 globals
(我在引入 application
模块之前这样做,前两行)。
require('globals');
require('nativescript-i18n');
如果您使用 TypeScript 并想在代码中使用 L()
,您需要将 global
变量转换为 any
,如下所示(在您打算使用 L()
的文件中)。您可以在 https://github.com/rborn/nativescript-i18n/issues/57 中了解更多信息。
declare var global:any;
在代码中使用它的方式如下
XML 文件
简单字符串
<Label text="{{ L('hello') }}">
它支持一个或多个替换,直接或从模型中替换
<Label text="{{ L('hello') }}" class="title" textWrap="true" />
<Label text="{{ L('hello_replace','my friend') }}" class="message" textWrap="true" />
<Label text title="{{ L('multi_replace','direct replacement', modelReplacement) }}">
假设您在 strings.xml 中定义了定义,并在模型中定义了替换 modelReplacement
变量
<string name="hello">Hello!</string>
<string formatted="false" name="hello_replace">Hello %s!</string>
<string formatted="false" name="multi_replace">We can replace directly in xml: %s or from the model: %s</string>
要为 i18n 文件定义自定义路径(除了 App_Resources/i18n
),将以下配置添加到项目的 package.json 中
"nativescript-i18n": {
"customLangPath": "app/resources/i18n"
}
如果手机的语言与您定义的语言不匹配,则默认为英语。如果您想设置自己的默认语言,请将以下配置添加到项目的 package.json 中
请注意,在 iOS 上,设备选择的语言将基于 设置
-> 语言与地区
-> 首选语言顺序
中的顺序
"nativescript-i18n": {
"defaultLang": "es"
}
重要
-
对于所有具有替换的字符串定义,您需要添加
formatted=false
-
引号和撇号需要转义,如下所示:
<string name="with_quotes">Apostrophe: \' and quotes: \"</string>
-
百分号需要通过设置
formatted="false"
并将其 加倍 来转义:<string formatted="false" name="percent"> Percent Sign: %%</string>
-
我们需要使用以下格式的 strings.xml,否则应用构建将失败
<?xml version="1.0" encoding="utf-8"?>
<resources>
</resources> -
我们需要在strings.xml中添加以下两行,以便应用程序正确编译。这也使得应用程序名称在iOS和Android上都实现了本地化,并在Android上设置了初始活动的标题。
<string name="app_name">demo</string>
<string name="title_activity_kimera">demo</string> -
有时,您可能需要完全从设备/模拟器中删除应用程序,以便插件完全工作(通常仅在插件在项目开发后期阶段安装时)。
-
如果您在TypeScript中遇到关于L未定义的抱怨,那么请在您的
references.d.ts
中添加以下内容:/// <reference path="./node_modules/nativescript-i18n/references.d.ts" /> Nativescript i18n
。
JS文件
console.log(L('home'));
console.log(L('multi_replace', 'ONE', 'TWO'));
Angular
如果您使用Angular来构建应用程序,那么事情会变得稍微复杂一些。
我的Angular技能为零,但@alejonext在此评论中为此提供了一个解决方案。
更新 28.06.2016
@AirMike 和 @loloof64 通过测试和进一步改进 @alejonext的PR,做了出色的工作,因此插件现在包括了Angular的支持:bow
在以常规方式将插件导入应用程序后,只需在您的文件(main.ts)中导入来自nativescript-i18n/angular
的NativeScriptI18nModule
模块即可。
(请注意,以下说明是针对TypeScript而非纯JS)
import { NativeScriptI18nModule } from "nativescript-i18n/angular";
然后在应用程序模块中导入它
@NgModule({
imports: [
NativeScriptI18nModule
]
})
export class AppModule { }
Angular的使用方式为:{{ value | L:args }}
<Button text="{{ 'Login' | L }}"></Button>
关于更详细的示例
您可以在main.ts中放入以下代码
import { NativeScriptI18nModule } from 'nativescript-i18n/angular';
import { NativeScriptModule } from "nativescript-angular/platform";
import { NgModule } from "@angular/core";
import { AppComponent } from "./app.component";
@NgModule({
imports: [
NativeScriptModule,
NativeScriptI18nModule
],
declarations: [
AppComponent,
],
bootstrap: [AppComponent]
})
export class AppModule { }
对于主组件,假设以下HTML模板被使用(字符串定义见下文)
<GridLayout rows="*,*,*">
<label row="0" text="{{'menuitem_new_file' | L }}"></label>
<label row="1" text="{{'menuitem_new_folder' | L }}"></label>
<label row="2" text="{{'menuitem_new' | L:'---':'***':124.25693 }}"></label>
</GridLayout>
以下是“en”的字符串定义(放入app/i18n/en/strings.xml中)
<resources>
<string name="app_name">Chess Exercices Cupboard</string>
<string name="title_activity_kimera">Chess Exercices Cupboard</string>
<string formatted="false" name="menuitem_new">%s New... %s %0.2f</string>
<string name="menuitem_new_file">File</string>
<string name="menuitem_new_folder">Folder</string>
</resources>
以下是法语翻译(放入app/i18n/fr/srings.xml中)
<resources>
<string name="app_name">Chess Exercices Cupboard</string>
<string name="title_activity_kimera">Chess Exercices Cupboard</string>
<string formatted="false" name="menuitem_new">%s Nouveau... %s %0.2f</string>
<string name="menuitem_new_file">Fichier</string>
<string name="menuitem_new_folder">Dossier</string>
</resources>
然后如果您的手机设置为法语,您会看到如下内容
Fichier
Dossier
--- Nouveau... *** 124.25693
或者,如果设置为英语或“未识别”语言
File
Folder
--- New... *** 124.25693
演示
请查看demo
文件夹以获取一个工作示例。
iOS权限文本
将这些特殊键添加到app/i18n/(lang)/strings.xml
中,用于在显示权限警报时通知用户,使用配置的语言。
键 | 键的说明 |
---|---|
NSAppleMusicUsageDescription | 指定您的应用程序使用媒体库的原因 |
NSBluetoothPeripheralUsageDescription | 指定您的应用程序使用蓝牙的原因 |
NSCalendarsUsageDescription | 指定您的应用程序访问用户日历的原因 |
NSCameraUsageDescription | 指定您的应用程序访问设备摄像头的原因 |
NSContactsUsageDescription | 指定您的应用程序访问用户联系人的原因 |
NSHealthShareUsageDescription | 指定您的应用程序读取用户健康数据的原因 |
NSHealthUpdateUsageDescription | 指定您的应用程序更改用户健康数据的原因 |
NSHomeKitUsageDescription | 指定您的应用程序访问用户HomeKit配置数据的原因 |
NSLocationAlwaysUsageDescription | 指定您的应用程序在所有时间访问用户位置信息的原因 |
NSLocationWhenInUseUsageDescription | 指定您的应用程序在应用程序使用时访问用户位置信息的原因 |
NSMicrophoneUsageDescription | 指定您的应用程序访问设备上任何麦克风的理由 |
NSMotionUsageDescription | 指定您的应用程序访问设备加速度计的原因 |
NSPhotoLibraryUsageDescription | 指定您的应用程序访问用户照片库的原因 |
NSRemindersUsageDescription | 指定您的应用程序访问用户提醒的原因 |
NSSiriUsageDescription | 指定您的应用程序向Siri发送用户数据的原因 |
NSSpeechRecognitionUsageDescription | 指定您的应用向苹果的语音识别服务器发送用户数据的理由 |
(伪)路线图/想法
以下想法受到此评论以及本插件用户的帖子启发
- [x] Android实现 - 使用
App_Resources/Android/values/
中的原生strings.xml
- [x] iOS实现 - 使用原生
Localizable.strings
文件(这些文件需要放在哪里?) - [x] 允许格式化字符串,例如:
L('hello', 'world')
翻译为hello %s
的定义(以及/或其他类型%d
等) - [ ] 可能需要一个命令行工具/命令来从我们的语言功能使用中提取字符串并将它们放入我们的strings.xml进行翻译
- [x] 将
app/i18n
中的strings.xml文件移动到正确位置(具体文件夹结构待定)并用作以下点的基准- [x] 在编译Android之前建立钩子以移动文件
- [x] 在编译iOS之前建立钩子以翻译和移动文件
- [ ] 关于资产(图片/启动屏幕等)怎么办?可能超出了此插件的范围
- [x] 应用程序名称怎么办?
- [ ] 我们是否需要一个模块级的缓存,这样我们就不必每次都跨越本地桥接?(应进行基准测试以决定此问题)
- [x] 使缓存了解当前语言和语言更改
- [x] Angular支持
- [x] 语言文件的自定义路径(《https://github.com/rborn/nativescript-i18n/issues/28》#28)
- [x] 设置应用程序的默认语言(《https://github.com/rborn/nativescript-i18n/issues/11》#11)
- [x] 在iOS的应用程序权限提示中显示翻译(《https://github.com/rborn/nativescript-i18n/issues/45》#45)
- [ ] 在某些文件无法创建的情况下报告错误
- [ ] Webpack支持(《https://github.com/rborn/nativescript-i18n/issues/49》#49,《https://github.com/NativeScript/NativeScript/issues/42》#42)