一键更新 iOS、Android、React Native 和 Flutter 应用程序的翻译,无需向 App Store 或 Google Play 发布新版本。文本标签更新即时推送到移动应用程序。
无线 OTA 还集成了 i18Next 和 Rails 平台,用户可以在网络应用程序中更新和管理本地化内容,而无需重新部署。
必须创建一个新版本订单应用更新的设置。
当用户在设备上首次启动应用了我们 iOS、Android、React Native 和 Flutter SDK 的 app 时,我们会随机生成一个唯一的设备标识符,该标识符跟踪给定时间段内的可用的用户。除此之外不作它用,也不保存任何用户或设备信息。
OTA 方面我们唯一的限制是月活用户(MAU)的数量,不同的套餐月活用户数量不同。
MAU 是请求翻译的设备数量。每个设备被分配一个随机 ID,MAU 是根据过去 30 天分配的不同 ID 的数量计算的。
数据
SDK 与 OTA 服务通信订单检查更新,并在每个请求中包括以下详细信息:
-
设备标识符(例如"F3AFCB10-80A2-84CB-94C0-27F5EF58876D".此应用程序唯一,因此不允许跟踪特定设备。)
-
应用程序版本(例如"1.2.0")
-
最后更新翻译文件(例如"1542187679")
-
SDK 版本(例如"1.0.0")
-
区域(例如“de-DE”)
-
文件格式(例如“字Strings”)
-
客户(例如“ios”)
-
分发 ID(分发的 ID)
-
环境秘密(区分开发和生产)
译文平台在分发中定义:
-
iOS
-
安卓
-
Flutter
-
i18next
-
Rails
可以有多个分发,但理想情况下每个项目有一个分发。如果使用 iOS 和 Android 分发,两种格式的占位符将自动转换。
回退
如果在分发连接的项目的语言设置中设置了语言回退,则如果请求的语言存在,但键未翻译,将显示来自选定语言的 Strings。
如果使用特定国家的语言(例如en-GB),但不属于版本的一部分,则系统可以恢复该项目中存在的该语言的标准版本(例如en)。如果根本找不到请求的语言,可以改用项目的默认区域。
创建分发
要创建分发,请执行以下步骤:
-
在配置或配置数量(如果已经存在)。
页面上的 Box 中,单击页面打开并显示现有配置。
-
单击新建分发。 窗口打开。
-
在常规选项卡中,提供 、分发与哪个 关联、所需 和所需 。
-
对于安卓分发,请单击安卓选项卡,根据需要选择在 CDATA 中包含任何翻译(包括 HTML tags)的格式选项。
-
选择要与分发关联的项目后,安排选项卡变为可用。如果需要,使用此选项卡在分发中设置 OTA 定时发布。
-
-
在回退语言选项卡中,根据需要选择特定分发的回退设置。回退选项的优先级如列表所示。
-
或者,单击翻译选项卡以选择使用最新已审校版本的翻译。
-
点击保存。
分发详细信息以 SDK 要求的 ID 显示。通过点击
页面的分发,可以再次显示详细信息。
要更新翻译,请在分发中创建一个新版本。将项目的当前状态导出并提供给已连接的客户。
要创建版本,请执行以下步骤:
-
在远程更新页面,点击所需分发旁边的添加版本。
窗口打开。
-
提供
、所需 、 、 和 。如有必要,输入 tags 以仅包括版本中包含特定 tags 的字符串。
-
点击保存。
版本将添加到分发详细信息页面底部的列表。
要设置发布分发的定期时间表,请执行以下步骤:
-
在
页面,单击所需分发旁边的齿轮图标。
此时将显示
窗口。 -
选择时间表发布选项卡,然后单击 。
将显示版本安排选项。
注释
在创建新分发时,计划选项也可用。
-
从
一个下拉列表中,通过选择一个可用选项来选择发布频率:-
-
为预定发布选择所需的工作日。
-
-
提供时间和相关
。 -
如有必要,为预定版本选择
、 和 。-
只有当项目中启用了分支时,才会显示
字段。选择分支将更新区域和语言列表。
-
-
(可选)在
和 字段中指定应用程序版本。留空以将时间表发布应用于应用程序的所有版本。
-
点击保存。
发布计划信息会更新分发。
禁用时间表将停止分发的自动发布,但已配置的设置将被保存。
通过集成适当的移动 SDK 或网络库,一键更新翻译,还可提供衡量使用情况的指标。移动 SDK 和 Web 库报告让您深入了解可用的应用程序用户及其应用程序语言。可以为每个分发访问这组报告,并且报告的数据每天更新两次。
为可用的用户数量、总体请求、每种语言的请求、每个平台的请求以及未提供的设备语言提供了报告。
通过图标访问每个分发的报告。
有了 SDK,应用程序会定期检查更新的翻译并在后台下载。
定期检查 Android SDK 的最新版本,特别是考虑升级。
如果翻译未更新:
-
确保分发ID和环境密码正确。
-
确保为当前应用程序版本创建了版本。
-
重新加载
ViewController
以立即显示更改。
如果正在使用错误的翻译版本,请确保具有最新翻译的版本和当前应用程序版本以及应用程序的版本名称
已设置并正在使用<严重>.<轻微>.<点>.
格式。
要求
-
SDK 至少需要 appcompat 版本 1.2.0。如果使用旧版本的 appcompat,请考虑使用 SDK 版本 2.1.3
-
该库依靠 AndroidX 支持向后兼容的用户界面元素,如工具栏。
包括 SDK
向根 build.gradle
添加新存储库:
allproject { 存储库 { …… maven { url "https://maven.download.phrase.com" } } }
将库添加为依赖项:
依赖项 { implementation "com.phrase.android:ota-sdk:3.5.0" …… }
Jetpack Compose 支持
要为 OTA 翻译启用 Jetpack Compose 支持,请执行以下步骤:
-
将库
实现“com.phrase.android:OTA-sdk-compose:3.5.0”
添加到根build.gradle
。 -
用
phrase {...
包装 Jetpack Compose 代码。
配置
在应用程序类中初始化 SDK 并添加分发 ID 和环境密码。从应用程序继承的类应覆盖 attachBaseContext
以启用活动上下文以外的翻译:
public class MainApplication 扩展了应用程序 { @Override public void onCreate() { super.onCreate(); Phrase.setup(this, "DISTRIBUTION_ID", "ENVIRONMENT_TOKEN"); Phrase.updateTranslations(); } @Override protected void attachBaseContext(Context newBase) { super.attachBaseContext(Phrase.wrapApplicationContext(newBase)); } }
在每个 Activity 中注入 SDK,例如创建一个所有其他 Activity 都继承自的基础 Activity:
public class BaseActivity 扩展了 AppCompatActivity { @NonNull @Override public AppCompatDelegate getDelegate() { return Phrase.getDelegate(this, super.getDelegate()); } }
翻译可以照常用于布局:
<TextView android:text="@string/translation_key" />
内部代码:
TextView text = (TextView) findViewById(R.id.text_id); text.setText(R.string.translation_key);
某些库不支持自动展开上下文,需要一个特定的类。在这种情况下,可以使用以下命令禁用 Jetpack Compose 组件中的上下文环绕:
Phrase(contextWrapping = false) { Text( text = phraseString(R.string.test) ) }
日志级别的配置:
-
Java
PhraseLog.setLogLevel(Severity.Debug);
-
科特林语
PhraseLog.logLevel = Severity.Verbose
-
其他支持的日志选项
-
无
-
错误
-
警告
-
详情
-
调试
-
动词
-
更改语言
如果没有使用系统语言,可以在“setLocaleCode
”方法中设置不同的语言。版本必须包含语言代码(区域)。
Phrase.setLocaleCode("fr"); Phrase.updateTranslations();
自定义应用程序版本
SDK 默认使用 app 版本返回与最低和最高版本版本版本约束相匹配的版本。应用程序版本必须使用语义版本控制,否则不会返回翻译更新。如果应用程序不使用语义版本控制,可以手动覆盖使用的应用程序版本。
示例:
Phrase.setAppVersion("3.2.4");
调用 updateTranslations()
之前必须设置版本。
设置超时
翻译下载的默认超时设置为 10 秒。
默认值可用以下命令更改:
Phrase.setTimeout(10000);// 以毫秒为单位的超时
更新回调
如果需要处理成功的翻译更新,请附加回调处理程序:
Phrase.updateTranslations(new TranslationsSyncCallback() { @Override public void onSuccess(boolean translationsChanged) { } @Override public void onFailure() { } });
还可以手动触发翻译更新。新获取的翻译将在下一个应用程序启动时显示。
要立即提供最新翻译,请使用方法 Phrase.applyPendingUpdates()
。这可以与收听翻译更新相结合:
Phrase.updateTranslations(new TranslationsSyncCallback() { @Override public void onSuccess(boolean translationsChanged) { if(translationsChanged) { Phrase.applyPendingUpdates() / / 自定义逻辑刷新用户界面 } } @Override public void onFailure() { } });
用户界面不会自动显示翻译,必须重新创建。
配置美国数据中心
phrase 美国数据中心也受支持。美国数据中心可通过以下方式配置:
Phrase.setHost("https://ota.us.phrase.com/")
回退
如果由于客户的网络连接缺失或服务中断而无法连接到 phrase,SDK 将使用资源文件中的捆绑翻译。建议定期更新 app 中的捆绑翻译。SDK 还在本地设备上缓存翻译。如果存在这样的缓存,它将使用下一个一次翻译更新。
SDK 使用最新版本进行翻译。如果应用的 versionName
已设置,将使用满足版本限制的最新版本。
添加新语言
在 phrase 中创建新语言并创建一个新版本。当用户的设备语言时,SDK 会获取该语言。建议在发布新应用程序版本时为新语言文件定期添加新的 strings.xml
,否则用户只能在第一次启动应用程序时看到由 Android 确定的备用翻译。
审计
SDK 已关闭原文/源语,无法查看或修改。如果这是公司的要求,可以提供审计。如有需要,请联系我们。
自定义视图支持
自定义视图可以使用风格化属性翻译。由于 TypedArray
不允许覆盖资源,需要在自定义视图中稍作更改:
-
科特林语示例
之前:
context.obtainStyledAttributes(attrs, R.styleable.CustomView, defStyleAttr, 0).use { text = it.getText(R.styleable.CustomView_android_text) }
之后:
context.obtainStyledAttributes(attrs, R.styleable.CustomView, defStyleAttr, 0).use { text = it.getTextWithPhrase(R.styleable.CustomView_android_text) }
-
Java 示例
之前:
final TypedArray ta = context. obtainStyledAttributes(attrs, R.styleable.CustomView, defStyleAttr, 0); try { setText(ta.getText(R.styleable.CustomView_android_text)); } finally { ta.recycle(); }
之后:
final TypedArray ta = context. obtainStyledAttributes(attrs, R.styleable.CustomView, defStyleAttr, 0); try { setText(PhraseTypedArray.getTextWithPhrase(ta, R.styleable.CustomView_android_text)); } finally { ta.recycle(); }
示例应用程序
有了 SDK,应用程序会定期检查更新的翻译并在后台下载。
要求
此库依赖于 0.18.0 版本的 Flutter intl 库。按照他们的指南 '%1!为应用程序添加本地化支持。
安装
在 pubspec.yaml 中添加 phrase:
依赖项: phrase: ^2.5.1 …… 国际:^0.18.0 flutter_localizations: sdk: flutter …… flutter: 生成:真 ……
与原文
库中一样,代码生成用于处理 ARB 文件。运行此命令以更新:
flutter pub run 短Phrase
使用 build_runner:
flutter pub run build_runner 手表
使用
在 main.dart
文件中初始化 phrase:
import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_gen/gen_l10n/phrase_localizations.dart'; import 'package:phrase/phrase.dart'; void main() { Phrase.setup("[DISTRIBUTION_ID]", "[ENVIRONMENT_ID]"); runApp(MyApp()); } class MyApp 扩展了 StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( 标题:“颤抖演示”、 //.. 本地化代表:PhraseLocalizations.localizationsDelegates, supportedLocales:PhraseLocalizations.supportedLocales, ); } }
访问消息:
Text(AppLocalizations.of(context)!.helloWorld);
自定义
更新行为
每次应用启动时,OTA 翻译都会更新。禁用用此:
Phrase.setup("[DISTRIBUTION_ID]", "[ENVIRONMENT_ID]", checkForUpdates: false);
手动更新:
Phrase.updateTranslations(context).then((_) => print("Done!"));
自定义应用程序版本
SDK 默认使用 app 版本返回与最低和最高版本版本版本约束相匹配的版本。应用程序版本必须使用语义版本控制,否则不会返回翻译更新。如果应用程序不使用语义版本控制,可以手动覆盖应用程序版本:可以手动覆盖应用程序版本:
Phrase.setup("[DISTRIBUTION_ID]", "[ENVIRONMENT_ID]", customAppVersion:"1.2.3");
配置美国数据中心
phrase 美国数据中心也受支持。可以通过在 SDK 配置中传递相关 API 主机名参数来选择美国数据中心:
Phrase.setup("[DISTRIBUTION_ID]", "[ENVIRONMENT_ID]", host:PhraseHost.us);
示例应用程序
有了 SDK,应用程序会定期检查更新的翻译并在后台下载。
还支持 Mac Catalyst。
SDK 可以手动或通过 Swift Package Manager、Carthage 或 Cocoa Pods 安装。
如果翻译未更新:
-
确保分发ID和环境密码正确。
-
确保为当前应用程序版本创建了版本。
-
重新加载
ViewController
以立即显示更改。
如果正在使用错误的翻译版本,请确保版本包含最新的翻译和当前可用的应用程序版本。
Swift 软件包管理器
添加公共存储库 URL(https://GitHub.com/Phrase/ios-sdk/)。Xcode 会自动处理安装的其余部分。
迦太基语
在您的 Cartfile 中添加以下行:
binary "https://raw.githubusercontent.com/phrase/ios-sdk/master/PhraseSDK.json" ~> 3.0.0
运行carthage更新并将PhraseApp. framework
""%1""添加到您的项目,如Carthage 文档中所述。
可可荚
在您的 Pod 文件中添加以下行:
pod“PhraseSDK”
运行pod安装。如果是 CocoaPods 新手,请参阅其文档。
手动安装
按照以下步骤操作:
-
下载最新版本。
-
在 Xcode 中添加
PhraseSDK.framework
作为译文的链接二进制文件。 -
在上传应用程序之前,需要运行一个脚本来剥离多余的二进制文件,因为苹果商店拒绝包括模拟器二进制文件在内的应用程序。
转到
并单击 + 符号添加一个 部分。粘贴在此脚本中:FRAMEWORK="PhraseSDK" FRAMEWORK_EXECUTABLE_PATH="${BUILT_PRODUCTS_DIR}/${FRAMEWORKS_FOLDER_PATH}/$FRAMEWORK.framework/$FRAMEWORK" EXTRACTED_ARCHS=() $ARCHS 中的 ARCH do lipo -extract "$ARCH" "$FRAMEWORK_EXECUTABLE_PATH" -o "$FRAMEWORK_EXECUTABLE_PATH-$ARCH" EXTRACTED_ARCHS+=("$FRAMEWORK_EXECUTABLE_PATH-$ARCH") 已完成 lipo -o "$FRAMEWORK_EXECUTABLE_PATH-merged" -create "${EXTRACTED_ARCHS[@]}" rm "${EXTRACTED_ARCHS[@]}" rm "$FRAMEWORK_EXECUTABLE_PATH" mv "$FRAMEWORK_EXECUTABLE_PATH-merged" "$FRAMEWORK_EXECUTABLE_PATH"
配置
-
导入 PhraseSDK:
导入 PhraseSDK
-
调用以下代码初始化 SDK:
Phrase.shared.setup( distributionID: <分发ID>, environmentSecret: <Environment Secret> )
-
要更新本地化文件,请调用
Phrase.shared.updateTranslation()
。如果 SDK 设置不正确,此方法将引发异常。
要将 OTA 配置为使用美国数据中心,请在调用
PhraseApp.shared.updateTranslation ()
之前设置主机,Phrase.shared.configuration.apiHost = .us
。
建议在 applicationDidFinishLaunchingWithOptions
方法的 AppDelegate
中调用这两个函数。
目标-C
将 SDK 集成到 Objective-C 应用程序中:
@import PhraseSDK; @implementation AppDelegate - (BOOL)应用程序:(UIApplication *)应用程序已完成启动选项:(NSDictionary *)启动选项 { [[Phrase shared] setDebugMode:true]; // Optional [[ phrase shared] setupWithDistribution ID:@"Your Distribution ID" environmentSecret:@"Your Environment Secret"]; // OR: // // [[Phrase shared] setupWithDistributionID:@"Your Distribution ID" // environmentSecret:@"Your Environment Secret" / / timeout:10]; // 使用回调块更新翻译: [[Phrase shared] updateTranslationsWithCompletionHandler:^(BOOL 已更新,NSError* 错误){ NSLog(@"Updated: %@", updated ? @"true" : @"false"); if (error) { NSLog(@"域:%@ 代码:%ld 消息:%@", error.domain, (long)error.code, error.localizedDescription); } other { NSLog(@"No error"); } // 通过捆绑包代理翻译: NSString *translation = NSLocalizedString(@"layouts.application.about", @""); NSLog(@"NSLocalizedString via bundle proxy: %@", translation); // OR: // // 使用回退方法翻译: NSString *otherTranslation = [[Phrase shared] localizedStringForKey:@"layouts.application.about" value:NULL table:NULL]; NSLog(@“Phrase.shared localizedStringForKey:%@”,otherTranslation); }]; // OR: // //[[短语共享] updateTranslationsWithCompletionHandler:NULL];//略过结果和错误(不推荐) // [...] 您的其他代码 return YES; }
禁用刷卡
要禁用刷卡,请在 Info.plist
文件中将 PhraseSDKMainBundleProxyDisabled
设置为 YES。
禁用刷卡时,不再显示更新的翻译。如果调用了 updateTranslation,
并且可以使用 Phrase.localizedString ()
方法访问,则翻译仍将同步。
应用程序版本处理
要确定应返回哪个版本,SDK 需要应用程序的语义版本,以便更新翻译。
SDK 尝试通过以下方式获取语义版本:
-
如果语义,则使用
CFBundleShortVersionString
。 -
如果没有,则在语义上使用
CFBundleVersion
。 -
如果两者语义不一致,则使用(
CFBundleShortVersionString.CFBundleVersion
)的组合。
如果缺少 CFBundleShortVersionString
或无法使用语义版本与 CFBundleVersion
一起创建,SDK 会抛出 PhraseSetupError.appVersionNotSemantic
消息。
禁用多个表格的翻译
要防止 OTA 翻译 iOS 主捆绑包中除默认可本地化
表外的任何表格,请设置以下选项:
Phrase.shared.configuration.ignoreOtherTables = true
回调
添加回调处理程序以处理成功的翻译更新:
Phrase.shared.updateTranslation { 结果 switch 结果 { case .success(let 已更新): case .failure: } }
调试模式
如果需要更多信息,启用调试模式以将 PhraseSDK. framework
额外登录到控制台:
Phrase.shared.configuration.debugMode = true
设置请求超时
通过调用以下命令为 phrase 设置请求超时:
Phrase.shared.configuration.timeout = TimeInterval(20)
默认超时为 10 秒,超过 10 秒的连接将被关闭。
提供手动语言覆盖
如果不使用系统语言作为区域,可以在初始化调用中设置不同的区域。区域代码需要出现在 phrase:
Phrase.shared.configuration.localeOverride = "en-US"
回退
如果无法通过 SDK 从 phrase 获取新翻译,请使用安装收到的最新翻译文件。如果 app 从未从 phrase 收到新文件,则使用 app 的编译翻译文件。这样可以避免出现任何技术困难或网络错误。建议在每次发布时都更新编译到 app 中的翻译文件。
审计
SDK 已关闭原文/源语,无法查看或修改。如果这是公司的要求,可以提供审计。如有需要,请联系我们。
有了 SDK,应用程序会定期检查更新的翻译并在后台下载。
OTA 翻译库仅与react-i18next 库一起使用。
要安装 React Native SDK,请执行以下步骤:
-
运行此命令:
$ npm install react-native-Phrase -- 保存
-
初始化 phrase:
从“react-native-phrase-sdk”导入 phrase; let phrase = new phrase( "YOUR_DISTRIBUTION_ID", "YOUR_DEVELOPMENT_OR_PRODUCTION_SECRET", "YOUR_APP_VERSION", "i18next" );
文件格式可以是
i18next
(如上面的例子)或i18next_4
,这样就形成了 i18next v4 格式文件。还支持 phrase 美国数据中心。要在美国数据中心使用 React Native SDK,请在初始化过程中通过相关主机:
从“react-native-phrase-sdk”导入 phrase; let phrase = new phrase( "YOUR_DISTRIBUTION_ID", "YOUR_DEVELOPMENT_OR_PRODUCTION_SECRET", "YOUR_APP_VERSION", "i18next", host="https://ota.us.phrase.com/" );
-
根据实例创建 i18next 后端:
从“i18next-resources-to-backend”导入 resourcesToBackend; const backendPhrase = resourcesToBackend((language, namespace, callback) => { phrase.requestTranslation(language) .then((remoteResources) => { callback(null, remoteResources); }) .catch((error) => { callback(error, null); }); }); const backendFallback = resourcesToBackend(localResources)
-
使用 phrase 后端初始化=%i18n=%:
i18n .use(ChainedBackend) .use(initReactI18next) .init({ 后端:{ backends: [backendPhrase, backendFallback] } //... });
示例 i18next.js
文件
从“i18next”导入i18n; import { initReactI18next } from "react-i18next"; 从“i18next-chained-backend”导入 ChainedBackend; 从“i18next-resources-to-backend”导入 resourcesToBackend; import translationEN from "./locales/en/translation.json"; import translationRU from "./locales/ru/translation.json"; 从“react-native-phrase-sdk”导入 phrase; const localResources = { en: { 翻译:Translaten, }, ru: { 翻译:translationRU, }, }; let phrase = new phrase( "YOUR_DISTRIBUTION_ID", "YOUR_ENVIRONMENT_ID", require('./package.json').version, "i18next" ); const backendPhrase = resourcesToBackend((language, namespace, callback) => { phrase.requestTranslation(language) .then((remoteResources) => { callback(null, remoteResources); }) .catch((error) => { callback(error, null); }); }); const backendFallback = resourcesToBackend(localResources) i18n .use(ChainedBackend) .use(initReactI18next) .init({ 后端:{ backends: [backendPhrase, backendFallback] }, debug: true, lng: "en", fallbackLng: "en", 插值:{ escapeValue: false, // 默认为逃逸,无需响应 } });
示例应用程序
i18next-Phrase-backend 库为 i18next 实现了一个示例“backend”。
要创建一个新版本,需要为该分发设置
平台并将其作为版本的一部分。使用
初始化 phrase:
从“i18next”导入i18n; import { I18nextPhraseBackend } from "@phrase/i18next-backend"; i18n .use(I18nextPhraseBackend) .init({ fallbackLng: 'en', 后端:{ 分发:'DISTRIBUTION_ID', 秘密:'YOUR_ENVIRONMENT_SECRET', appVersion:'1.0.0', } });
缓存
库正在缓存翻译,5 分钟内不会检查新翻译。出于测试目的,可以在后端配置中设置 cacheExpirationTime
选项来配置缓存。
i18n .use(I18nextPhraseBackend) .init({ fallbackLng: 'en', 后端:{ 分发:'DISTRIBUTION_ID', 秘密:'YOUR_ENVIRONMENT_SECRET', appVersion:'1.0.0', cacheExpirationTime:60* 5,// 秒 } });
注释
建议在生产环境中使用至少 5 分钟的缓存时间。
示例应用程序
Phrase-OTA-i18n 库实现了一个后端实例,用于从 OTA 版本检索翻译的 I18n gem。通过存储库,应用程序定期检查更新的翻译并在后台下载。
该库对任何使用 i18n gem 的 Ruby 应用程序都有效。
要创建一个新版本,需要为分发设置
平台并将其作为版本的一部分。安装
使用
生成配置:
bundle exec Rails 生成 Phrase_ota:install --distribution-ID <DISTRIBUTION_ID> --secret-令牌 <SECRET>
调试
gem 有一个调试
配置,可以通过设置在初始化器中启用:
config.debug = true