如何强制 NSLocalizedString 使用特定语言
在 iPhone 上,NSLocalizedString
返回 iPhone 语言的字符串。 是否可以强制 NSLocalizedString
使用特定语言来安装应用程序 使用与设备不同的语言?
On iPhone NSLocalizedString
returns the string in the language of the iPhone.
Is it possible to force NSLocalizedString
to use a specific language to have the app
in a different language than the device ?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(28)
NSLocalizedString()
(及其变体)访问NSUserDefaults
中的“AppleLanguages”键来确定用户的首选语言设置。这将返回一组语言代码,第一个是用户为其手机设置的语言代码,如果资源在首选语言中不可用,则后续的代码将用作后备。 (在桌面上,用户可以通过系统偏好设置中的自定义顺序指定多种语言)如果您愿意,可以使用 setObject:forKey: 方法设置您自己的语言列表,从而覆盖您自己的应用程序的全局设置。这将优先于全局设置值,并返回到应用程序中执行本地化的任何代码。其代码如下所示:
这将使德语成为您应用程序的首选语言,英语和法语作为后备语言。您可能希望在应用程序启动初期调用此函数。您可以在此处阅读有关语言/区域设置首选项的更多信息:国际化编程主题:获取当前语言和区域设置
NSLocalizedString()
(and variants thereof) access the "AppleLanguages" key inNSUserDefaults
to determine what the user's settings for preferred languages are. This returns an array of language codes, with the first one being the one set by the user for their phone, and the subsequent ones used as fallbacks if a resource is not available in the preferred language. (on the desktop, the user can specify multiple languages with a custom ordering in System Preferences)You can override the global setting for your own application if you wish by using the setObject:forKey: method to set your own language list. This will take precedence over the globally set value and be returned to any code in your application that is performing localization. The code for this would look something like:
This would make German the preferred language for your application, with English and French as fallbacks. You would want to call this sometime early in your application's startup. You can read more about language/locale preferences here: Internationalization Programming Topics: Getting the Current Language and Locale
我最近遇到了同样的问题,我不想启动并修补整个 NSLocalizedString ,也不想强制应用程序重新启动以使新语言正常工作。我希望一切都能按原样进行。
我的解决方案是动态更改主包的类并在其中加载适当的包:
头文件
实现
所以基本上,当您的应用程序启动时和加载第一个控制器之前,只需call:
当您的用户在设置屏幕中更改其首选语言时,只需再次调用即可:
要重置回系统默认值,只需传递 nil:
享受...
对于那些需要 Swift 版本的人:
I had the same problem recently and I didn't want to start and patch my entire NSLocalizedString nor force the app to restart for the new language to work. I wanted everything to work as-is.
My solution was to dynamically change the main bundle's class and load the appropriate bundle there:
Header file
Implementation
So basically, when your app starts and before you load your first controller, simply call:
When your user changes his preferred language in your setting screen, simply call it again:
To reset back to system defaults, simply pass nil:
Enjoy...
For those who need a Swift version:
我通常以这种方式执行此操作,但您的项目中必须包含所有本地化文件。
I usually do this in this way, but you MUST have all localization files in your project.
不要在 iOS 9 上使用。这对于通过它的所有字符串都会返回 nil。
我找到了另一种解决方案,允许您更新语言字符串,无需重新启动应用程序并与 genstrings 兼容
: Prefix.pch 中的此宏:
以及在需要本地化字符串的地方使用:
设置语言使用:
甚至可以使用连续的语言跳跃,例如:
Do not use on iOS 9. This returns nil for all strings passed through it.
I have found another solution that allows you to update the language strings, w/o restarting the app and compatible with genstrings:
Put this macro in the Prefix.pch:
and where ever you need a localized string use:
To set the language use:
Works even with consecutive language hopping like:
如前所述,只需执行以下操作:
但为了避免重新启动应用程序,请将此行放在
main.m
的 main 方法中,就在UIApplicationMain
(...) 。As said earlier, just do:
But to avoid having to restart the app, put the line in the main method of
main.m
, just beforeUIApplicationMain
(...).通过从应用程序中选择特定语言来使用特定语言的技巧是强制 NSLocalizedString 根据所选语言使用特定包,
这是我为此编写的帖子
学习 iOS 应用中的高级本地化
以下是一个示例应用的代码iOS 应用中的高级本地化
The trick to use specific language by selecting it from the app is to force the
NSLocalizedString
to use specific bundle depending on the selected language ,here is the post i have written for this
learning advance localization in ios apps
and here is the code of one sample app advance localization in ios apps
您对 Swift 3 的这个解决方案有何看法?
简单用法:
What do you think about this solution for Swift 3?
Simple usage:
正如 Brian Webster 提到的,需要“在应用程序启动的早期”设置语言。我认为
AppDelegate
的applicationDidFinishLaunching:
应该是执行此操作的合适位置,因为它是我执行所有其他初始化的位置。但正如 William Denniss 提到的,这似乎只有在应用程序重新启动后才有效,这有点无用。
不过,如果我将代码放在主函数中,它似乎工作得很好:如果
对此有任何评论,我将不胜感激。
As Brian Webster mentions, the language needs to be set "sometime early in your application's startup". I thought
applicationDidFinishLaunching:
of theAppDelegate
should be a suitable place to do it, since it's where I do all other initialization.But as William Denniss mentions, that seems to have an effect only after the app is restarted, which is kind of useless.
It seems to work fine if I put the code in the main function, though:
I'd appreciate any comments on this.
NSLocalizedString()
从标准用户默认值 ([NSUserDefaults standardUserDefaults]
) 中读取键AppleLanguages
的值。它使用该值在运行时从所有现有本地化中选择适当的本地化。当 Apple 在应用程序启动时构建用户默认字典时,他们会在系统首选项中查找首选语言键并从那里复制值。这也解释了为什么更改 OS X 中的语言设置对正在运行的应用程序没有影响,只会影响此后启动的应用程序。复制后,该值不会仅仅因为设置更改而更新。这就是为什么如果您更改语言,iOS 会重新启动所有应用程序。但是,用户默认字典的所有值都可以被命令行参数覆盖。请参阅有关
NSArgumentDomain
的NSUserDefaults
文档。这甚至包括从应用程序首选项 (.plist) 文件加载的那些值。如果您只想更改一次值进行测试,那么了解这一点非常有用。。因此,如果您想更改语言只是为了测试,您可能不想更改您的代码(如果您稍后忘记删除此代码......),而是告诉 Xcode 使用命令行参数启动您的应用程序(例如使用西班牙语本地化):
根本不需要修改您的代码。只需为不同的语言创建不同的方案,您只需切换方案即可快速启动应用程序,一次以一种语言启动,一次以另一种语言启动。
NSLocalizedString()
reads the value for the keyAppleLanguages
from the standard user defaults ([NSUserDefaults standardUserDefaults]
). It uses that value to choose an appropriate localization among all existing localizations at runtime. When Apple builds the user defaults dictionary at app launch, they look up the preferred language(s) key in the system preferences and copy the value from there. This also explains for example why changing the language settings in OS X has no effect on running apps, only on apps started thereafter. Once copied, the value is not updated just because the settings change. That's why iOS restarts all apps if you change then language.However, all values of the user defaults dictionary can be overwritten by command line arguments. See
NSUserDefaults
documentation on theNSArgumentDomain
. This even includes those values that are loaded from the app preferences (.plist) file. This is really good to know if you want to change a value just once for testing.So if you want to change the language just for testing, you probably don't want to alter your code (if you forget to remove this code later on ...), instead tell Xcode to start your app with a command line parameters (e.g. use Spanish localization):
No need to touch your code at all. Just create different schemes for different languages and you can quickly start the app once in one language and once in another one by just switching the scheme.
我最喜欢 Mauro Delrio 的方法。
我还在 Project_Prefix.pch 中添加了以下内容,
因此,如果您想使用标准方法(使用 NSLocalizedString),您可以在所有文件中进行快速语法替换。
I like best Mauro Delrio's method.
I also have added the following in my Project_Prefix.pch
So if you ever want to use the standard method (that uses NSLocalizedString) you can make a quick syntax substitution in all files.
我想出了一个允许您使用 NSLocalizedString 的解决方案。我创建了一个
NSBundle
调用NSBundle+RunTimeLanguage
的类别。界面是这样的。实现是这样的。
不仅仅是将 import
NSBundle+RunTimeLanguage.h
添加到使用NSLocalizedString
的文件中。如您所见,我将 languageCode 存储在
AppDelegate
的属性中。这可以存储在您想要的任何地方。我唯一不喜欢的是
NSLocalizedString
marco 重新定义的警告。也许有人可以帮我修复这部分。I came up with a solution that allows you to use
NSLocalizedString
. I create a category ofNSBundle
callNSBundle+RunTimeLanguage
. The interface is like this.The implementation is like this.
Than just add import
NSBundle+RunTimeLanguage.h
into the files that useNSLocalizedString
.As you can see I store my languageCode in a property of
AppDelegate
. This could be stored anywhere you'd like.This only thing I don't like about it is a Warning that
NSLocalizedString
marco redefined. Perhaps someone could help me fix this part.斯威夫特版本:
Swift Version:
Swift 3 扩展:
用法:
Swift 3 extensions:
Usage:
在 swift 4 中,我已经解决了这个问题,无需重新启动或使用库。
尝试了很多选项后,我找到了这个函数,您可以在其中传递要翻译的 stringToLocalize(Localized.String,字符串文件)、要翻译的语言以及它返回的内容是 Strings 文件中该字符串的值:
考虑到此函数,我在 Swift 文件中创建了此函数:
要从整个应用程序以及其余 ViewController 的每个字符串中访问,而不是输入:
I已将其替换为
我不知道这是否是最好的方法,但我发现它非常简单,并且对我有用,希望对您有帮助!
In swift 4, I have solved it without needing to restart or use libraries.
After trying many options, I found this function, where you pass the stringToLocalize (of Localizable.String, the strings file) that you want to translate, and the language in which you want to translate it, and what it returns is the value for that String that you have in Strings file:
Taking into account this function, I created this function in a Swift file:
To access from the whole app, and in each string of the rest of ViewControllers, instead of putting:
I have replaced it with
I do not know if it's the best way, but I found it very simple, and it works for me, I hope it helps you!
简而言之:
本地化您的应用程序
您要做的第一件事就是使用至少两种语言(本例中为英语和法语)本地化您的应用程序。
覆盖 NSLocalizedString
在您的代码中,不要使用
NSLocalizedString(key, comment)
,而是使用如下定义的宏MYLocalizedString(key, comment)
:#define MYLocalizedString(key, comment) [[MYLocalizationSystem sharedInstance] localizedStringForKey:(key) value:(comment)];
此
MYLocalizationSystem
单例将:设置用户语言
当用户将应用程序语言更改为法语时,调用
[[MYLocalizationSystem sharedInstance] setLanguage :@"fr"];
在此示例中 此方法将本地化包设置为 fr.lproj
返回本地化字符串
设置本地化包后,您将能够获取使用此方法从他那里得到正确的本地化字符串:
希望这会对您有所帮助。
您可以在 NSWinery 的这篇文章中找到更多详细信息。 io
In a nutshell :
Localize your application
It's the first thing you have to do is to localise your app with at least two languages (english and french in this example).
Override NSLocalizedString
In your code, instead of using
NSLocalizedString(key, comment)
, use a macroMYLocalizedString(key, comment)
defined like this :#define MYLocalizedString(key, comment) [[MYLocalizationSystem sharedInstance] localizedStringForKey:(key) value:(comment)];
This
MYLocalizationSystem
singleton will :Set user language
When user changed application language in french, call
[[MYLocalizationSystem sharedInstance] setLanguage:@"fr"];
In this example this method set localized bundle to fr.lproj
Return localized string
Once you've set the localized bundle, you'll be able to get the right localised string from him with this method :
Hope this will help you.
You'll find more details in this article from NSWinery.io
在文件.pch中定义:
In file .pch to define:
也许你应该补充这个(在 #import 之后的 .pch 文件上):
Maybe you should complement with this (on .pch file after #import ):
Swift 3解决方案:
给出了一些可以使用的语言代码的示例。希望这有帮助
Swift 3 solution:
Gave some examples of language codes that can be used. Hope this helps
您可以使用要执行此操作的一组本地化字符串构建一个子包,然后使用
NSLocalizedStringFromTableInBundle()
加载它们。 (我假设这是与您可能在应用程序上执行的正常 UI 本地化分开的内容。)You could build a sub-bundle with the set of localized strings that you want to do this with, and then use
NSLocalizedStringFromTableInBundle()
to load them. (I'm assuming that this is content separate from the normal UI localization you might be doing on the app.)对于我的情况,我有两个本地化文件,ja和en
,如果系统中的首选语言既不是en也不是ja,我想强制它为en,
我将编辑main.m文件,
我将检查第一个是否首选是 en 或 ja ,如果不是,那么我会将第二首选语言更改为 en。
for my case i have two localized file , ja and en
and i would like to force it to en if the preferred language in the system neither en or ja
i'm going to edit the main.m file
i 'll check whether the first preferred is en or ja , if not then i 'll change the second preferred language to en.
你可以这样做:
You can do something like this:
这是解决此问题的一个不错的解决方案,并且不需要重新启动应用程序。
https://github.com/cmaftuleac/BundleLocalization
此实现通过在 NSBundle 内部进行调整来实现。这个想法是,您在 NSBundle 对象的实例上重写 localizedStringForKey 方法,然后在使用不同语言的不同包上调用此方法。简洁大方,完全兼容各类资源。
Here is a decent solution for this problem, and it does not require application restart.
https://github.com/cmaftuleac/BundleLocalization
This implementation works by tweaking inside NSBundle. The idea is that you override the method localizedStringForKey on the instance of NSBundle object, and then call this method on a different bundle with a different language. Simple and elegant fully compatible with all types of resources.
基于 Tudorizer 的答案,无需离开或重新启动应用程序即可更改语言。
使用类来按顺序访问首选语言,而不是宏检查是否存在特定的语言代码。
下面是一个用于获取适用于 iOS 9 的当前语言包的类:
使用上面的类来引用字符串文件/图像/视频/等:
如下所示更改内联语言或更新“changeCurrentLanguage”方法上面的类采用引用新语言的字符串参数。
Based on Tudorizer's answer to change language without leaving or restarting the application.
Instead of a macro, use a class for accessing the preferred language in order to check if a specific language code is present.
Below is a class used to obtain the current language bundle that is working for iOS 9:
Use the class above to reference a string file / image / video / etc:
Change language in-line like below or update the "changeCurrentLanguage" method in the class above to take a string parameter referencing the new language.
此函数将尝试获取当前语言的本地化字符串,如果未找到,它将使用英语获取它。
This function will try to get localized string for current language and if it's not found it will get it using english language.
我想添加对 iOS 未正式支持的语言的支持(未在系统设置下的语言部分列出)。按照 Apple 的国际化教程 以及 Brian Webster 和 geon 的一些提示,我想出了这段代码(将其放在 main.m 中):
这对于 Storyboard 和 NSLocalizedString 代码都很有效。该代码假设用户稍后可以选择手动更改应用程序内的语言。
当然,不要忘记添加正确的 Storyboard 翻译和 Localized.strings 翻译(有关如何执行此操作的信息,请参阅上面的 Apple 页面链接)。
I wanted to add support for a language that isn't officially supported by iOS (not listed in Language section under system settings). By following the Apple's Internationalization Tutorial and few hints here by Brian Webster and geon, I came up with this piece of code (put it in main.m):
This works well for both Storyboard and NSLocalizedString code. The code assumes that user will have an option to manually change language inside app later on.
Of course, don't forget to add proper Storyboard translations and Localizable.strings translations (see link to Apple page above for how to do that).
对于 Swift,您可以覆盖
main.swift
文件并在应用运行之前在其中设置 UserDefaults 字符串。这样您不必重新启动应用程序即可看到所需的效果。与删除
AppDelegate.swift
文件中的@UIApplicationMain
配合使用。For Swift you can override the
main.swift
file and set the UserDefaults string there before you app runs. This way you do not have to restart the App to see the desired effect.paired together with the removal of
@UIApplicationMain
in yourAppDelegate.swift
file.对于我这个测试计划用户来说,在测试计划的
启动时传递的参数
中指定-AppleLanguages (en_BZ)
(伯利兹英语)是有效的。由于我们使用 en_GB 和 en_BZ,iOS 总是首选 en_GB。即使如此,当我将设备语言切换为 EN、将区域切换为 BZ 以及在测试计划
应用程序语言
和应用程序区域
设置中设置这些值时。除了上面的旧参数方法之外,没有任何帮助:)For me, Test-Plan user, specifying
-AppleLanguages (en_BZ)
(English Belize) in the TestPlan'sArguments Passed On Launch
is working.Since we use en_GB and en_BZ, iOS always preferred en_GB. Even so when I switched the devices language to EN and the region to BZ and when setting these values in the Test Plans
Application Language
andApplication Region
settings . Nothing helped except the good old arguments approach above :)无论你们做什么,最好的方法是获取指定语言的短名称,即:fr、en、nl、de、it 等...并将其分配给全局值。
使选择器视图像下拉菜单一样弹出(单击按钮的组合,从下面会出现选择器视图和语言列表),然后选择您想要的语言。让短名称存储在内部。
创建一个名为 LocalizedString 的 .h + .m 文件。
将short_name的全局值设置为等于LocalizedString.m中获取的值
选择所需的语言后,分配 NSBundlePath 来为所需的语言创建项目子目录。例如,nl.proj、en.proj。
当选择特定的项目文件夹时,调用相应语言的本地化字符串并动态更改语言。
没有违反规则。
whatever you all do, the best way is to take the short_name for the specified language, i.e.: fr, en, nl, de, it, etc... and assign the same to a global value.
make a picker view to pop up like a drop down menu (combination of a button on click of which a picker view appears from below with a list of languages) and select the language you desire. let the short name be stored internally.
make a .h + .m file named LocalisedString.
Set the global value of short_name to be equal to the obtained value in LocalisedString.m
When the required language is selected assign the NSBundlePath to create project sub-directories for the needed language. for eg, nl.proj, en.proj.
When the particular proj folder is selected call the localised string for the respective language and change the language dynamically.
no rules broken.