在 Javascript 中本地化字符串

IT技术 javascript .net localization resx
2021-03-03 12:45:19

我目前正在使用.resx文件来管理我的 .NET 服务器端资源。

我正在处理的应用程序还允许开发人员将 JavaScript 插入各种事件处理程序中以进行客户端验证等。对我来说,本地化 JavaScript 消息和字符串的最佳方法是什么?

理想情况下,我想将字符串存储在.resx文件中,以便将它们与其他本地化资源一起保存。

我愿意接受建议。

6个回答

一个基本的 JavaScript 对象是一个关联数组,因此它可以很容易地用于存储键/值对。因此,使用JSON,您可以为每个要本地化的字符串创建一个对象,如下所示:

var localizedStrings={
    confirmMessage:{
        'en/US':'Are you sure?',
        'fr/FR':'Est-ce que vous êtes certain?',
        ...
    },

    ...
}

然后你可以像这样获得每个字符串的语言环境版本:

var locale='en/US';
var confirm=localizedStrings['confirmMessage'][locale];
由于我编写 OO JS,每个对象都定义了它在原型上使用的默认英文字符串。如果我需要另一种语言,我只需加载另一个文件来修改原型字符串。这样我就不需要一次加载一种语言的所有字符串(它们是动态加载的)。缺点是您可能需要跨对象重复某些字符串。
2021-04-18 12:45:19
简单地反转“localizedStrings[culture][key]”的顺序就解决了加载多种文化的问题。 '不定义特定的键)
2021-04-22 12:45:19
这种方法的问题在于您加载所有语言的所有字符串。然而,服务器可能会通过浏览器提供的线索或通过用户偏好知道需要什么语言。发送单个语言文件会更好。
2021-04-27 12:45:19
我正在使用T4生成上面建议的代码。
2021-05-05 12:45:19

SproutCore启发您可以设置字符串的属性:

'Hello'.fr = 'Bonjour';
'Hello'.es = 'Hola';

然后根据您的语言环境简单地吐出正确的本地化:

var locale = 'en';
alert( message[locale] );

在谷歌搜索了很多并且对提出的大多数解决方案不满意之后,我刚刚找到了一个使用T4 模板的惊人/通用解决方案您可以在此处阅读Jochen van Wylick的完整帖子

使用 T4 基于 .resx 文件本地化 JavaScript 资源

主要优点是:

  1. 只有 1 个管理资源的地方(即 .resx 文件)
  2. 支持多种文化
  3. 利用 IntelliSense - 允许代码完成

缺点:

这个方案的缺点当然是.js文件的大小可能会变得非常大。然而,由于它被浏览器缓存,我们不认为这对我们的应用程序来说是一个问题。但是 - 这种缓存也可能导致浏览器找不到从代码调用的资源。


这是如何工作的?

基本上他定义了一个指向你的 .resx 文件的 T4 模板。使用一些 C# 代码,他遍历每个资源字符串并将其添加到 JavaScript 纯键值属性中,然后将这些属性输出到名为的单个 JavaScript 文件中Resources.js(您可以根据需要调整名称)。


T4 模板[相应更改以指向您的 .resx 文件位置]

<#@ template language="C#" debug="false" hostspecific="true"#>
<#@ assembly name="System.Windows.Forms" #>
<#@ import namespace="System.Resources" #>
<#@ import namespace="System.Collections" #>
<#@ import namespace="System.IO" #>
<#@ output extension=".js"#>
<#
 var path = Path.GetDirectoryName(Host.TemplateFile) + "/../App_GlobalResources/";
 var resourceNames = new string[1]
 {
  "Common"
 };

#>
/**
* Resources
* ---------
* This file is auto-generated by a tool
* 2012 Jochen van Wylick
**/
var Resources = {
 <# foreach (var name in resourceNames) { #>
 <#=name #>: {},
 <# } #>
};
<# foreach (var name in resourceNames) {
 var nlFile = Host.ResolvePath(path + name + ".nl.resx" );
 var enFile = Host.ResolvePath(path + name + ".resx" );
 ResXResourceSet nlResxSet = new ResXResourceSet(nlFile);
 ResXResourceSet enResxSet = new ResXResourceSet(enFile);
#>

<# foreach (DictionaryEntry item in nlResxSet) { #>
Resources.<#=name#>.<#=item.Key.ToString()#> = {
 'nl-NL': '<#= ("" + item.Value).Replace("\r\n", string.Empty).Replace("'","\\'")#>',
 'en-GB': '<#= ("" + enResxSet.GetString(item.Key.ToString())).Replace("\r\n", string.Empty).Replace("'","\\'")#>'
 };
<# } #>
<# } #>

在表单/视图端

要获得正确的翻译,如果您使用的是 WebForms,请在您的母版中添加以下内容:

<script type="text/javascript">

    var locale = '<%= System.Threading.Thread.CurrentThread.CurrentCulture.Name %>';

</script>

<script type="text/javascript" src="/Scripts/Resources.js"></script>

如果你使用 ASP.NET MVC(像我一样),你可以这样做:

<script type="text/javascript">

    // Setting Locale that will be used by JavaScript translations
    var locale = $("meta[name='accept-language']").attr("content");

</script>

<script type="text/javascript" src="/Scripts/Resources.js"></script>

MetaAcceptLanguage我从 Scott Hanselman 这篇很棒的帖子中得到帮助:

ASP.NET MVC 3、JavaScript 和 jQuery 中的全球化、国际化和本地化 - 第 1 部分

public static IHtmlString MetaAcceptLanguage<T>(this HtmlHelper<T> html)
{
     var acceptLanguage =
         HttpUtility.HtmlAttributeEncode(
                     Thread.CurrentThread.CurrentUICulture.ToString());

      return new HtmlString(
      String.Format("<meta name=\"{0}\" content=\"{1}\">", "accept-language",
                    acceptLanguage));
 }

用它

var msg = Resources.Common.Greeting[locale];
alert(msg);

使用附属程序集(而不是 resx 文件),您可以枚举服务器上知道该语言的所有字符串,从而生成一个 Javascript 对象,其中仅包含正确语言的字符串。

像这样的东西对我们有用(VB.NET 代码):

Dim rm As New ResourceManager([resource name], [your assembly])
Dim rs As ResourceSet = 
    rm.GetResourceSet(Thread.CurrentThread.CurrentCulture, True, True)
For Each kvp As DictionaryEntry In rs
    [Write out kvp.Key and kvp.Value]
Next

但是,遗憾的是,我们还没有找到对 .resx 文件执行此操作的方法。

JSGettext 做得非常出色——在后端使用几乎任何语言动态加载 GNU Gettext .po 文件。谷歌搜索“使用 Gettext 和 PHP 进行动态 Javascript 本地化”以找到使用 PHP 的 JSGettext 演练(我会发布链接,但这个愚蠢的网站不会让我叹息......)

编辑应该是链接