Локализовать строки в Javascript - PullRequest
38 голосов
/ 19 сентября 2008

В настоящее время я использую .resx файлы для управления серверными ресурсами для .NET.

приложение, с которым я имею дело, также позволяет разработчикам вставлять JavaScript в различные обработчики событий для проверки на стороне клиента и т. Д. Каков лучший способ локализации моих сообщений и строк JavaScript?

В идеале я хотел бы хранить строки в файлах .resx, чтобы они оставались с остальными локализованными ресурсами.

Я открыт для предложений.

Ответы [ 12 ]

25 голосов
/ 19 сентября 2008

Базовый объект 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];
13 голосов
/ 19 сентября 2008

Вдохновленный SproutCore Вы можете установить свойства строки:

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

, а затем просто выкладывайте правильную локализацию в зависимости от вашей локали:

var locale = 'en';
alert( message[locale] );
10 голосов
/ 09 февраля 2013

После большого количества поисков в Google и неудовлетворенности большинством представленных решений, я только что нашел удивительное / универсальное решение, которое использует T4 шаблонов . Полный пост Йохен ван Вайлик вы можете прочитать здесь:

Использование T4 для локализации ресурсов JavaScript на основе файлов .resx

Основные преимущества:

  1. Наличие только 1 места, где ресурсы управляются (а именно .resx файлы)
  2. Поддержка нескольких культур
  3. Использование IntelliSense - допускать завершение кода

Недостатки:

Недостатки этого решения, конечно, в том, что размер Файл .js может стать довольно большим. Тем не менее, так как он кэшируется браузер, мы не считаем это проблемой для нашего приложения. тем не мение - это кэширование также может привести к тому, что браузер не найдет ресурс, вызванный из кода.


Как это работает?

По сути, он определил шаблон T4, который указывает на ваши файлы .resx. С помощью некоторого кода на 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, который я получил от этого удивительного поста Скотта Хансельмана:

Глобализация, интернационализация и локализация в 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);
4 голосов
/ 29 мая 2009

JSGettext отлично справляется со своей задачей - динамическая загрузка файлов GNU Gettext .po с использованием практически любого языка на сервере. Google для "Динамической локализации Javascript с Gettext и PHP", чтобы найти пошаговое руководство для JSGettext с PHP (я бы опубликовал ссылку, но этот глупый сайт не даст мне, вздох ...)

Редактировать : это должно быть ссылкой

4 голосов
/ 10 ноября 2008

С помощью спутниковой сборки (вместо файла 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.

4 голосов
/ 19 сентября 2008

Я бы использовал обозначение объекта / массива:

var phrases={};
phrases['fatalError'] ='On no!';

Затем вы можете просто поменять файл JS или использовать Ajax-вызов, чтобы переопределить ваш список фраз.

3 голосов
/ 15 ноября 2012

Есть библиотека для локализации приложений JavaScript: https://github.com/wikimedia/jquery.i18n

Может выполнять замену параметров, поддерживает пол (умная обработка он / она), число (умная обработка множественного числа, включая языки, которые имеют более чем одну форму множественного числа) и пользовательские правила грамматики, которые нужны некоторым языкам.

Строки хранятся в файлах JSON.

Единственное требование - jQuery.

2 голосов
/ 22 августа 2011

Я сделал следующее для локализации JavaScript для мобильного приложения, работающего на HTML5:

1.Создали набор файлов ресурсов для каждого языка, назвав их «en.js» для английского языка. Каждый из них содержал различные строки приложения следующим образом:


        var localString = {
        appName: "your app name",
        message1: "blah blah"
      };

2.Используется Lazyload для загрузки подходящего файла ресурсов в зависимости от языка приложения: https://github.com/rgrove/lazyload

3.Пропишите код языка через строку запроса (поскольку я запускаю html-файл с Android с помощью PhoneGap)

4. Затем я написал следующий код для динамической загрузки соответствующего файла ресурсов:


var lang = getQueryString("language");
localization(lang);
function localization(languageCode) {
    try {
        var defaultLang = "en";
        var resourcesFolder = "values/";
        if(!languageCode || languageCode.length == 0)
            languageCode = defaultLang;
        // var LOCALIZATION = null;
        LazyLoad.js(resourcesFolder + languageCode + ".js", function() {
            if( typeof LOCALIZATION == 'undefined') {
                LazyLoad.js(resourcesFolder + defaultLang + ".js", function() {
                    for(var propertyName in LOCALIZATION) {
                        $("#" + propertyName).html(LOCALIZATION[propertyName]);
                    }
                });
            } else {
                for(var propertyName in LOCALIZATION) {
                    $("#" + propertyName).html(LOCALIZATION[propertyName]);
                }
            }
        });
    } catch (e) {
        errorEvent(e);
    }
}
function getQueryString(name)
{
  name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
  var regexS = "[\\?&]" + name + "=([^&#]*)";
  var regex = new RegExp(regexS);
  var results = regex.exec(window.location.href);
  if(results == null)
    return "";
  else
    return decodeURIComponent(results[1].replace(/\+/g, " "));
}

5. Из html-файла я ссылаюсь на строки следующим образом:


    span id="appName"
1 голос
/ 17 октября 2014

Ну, я думаю, что вы можете рассмотреть это. Англо-испанский пример:

Напишите 2 сценария Js, например:

en-GB.js
lang = {
    date_message: 'The start date is incorrect',
    ...
};
es-ES.js
lang = {
    date_message: 'Fecha de inicio incorrecta',
    ...
};

Серверная часть - код позади:

Protected Overrides Sub InitializeCulture()
    Dim sLang As String 
    sLang = "es-ES" 

    Me.Culture = sLang
    Me.UICulture = sLang
    Page.ClientScript.RegisterClientScriptInclude(sLang & ".js", "../Scripts/" & sLang & ".js")

    MyBase.InitializeCulture()
End Sub

Где sLang может быть "en-GB", вы знаете, в зависимости от выбора текущего пользователя ...

Javascript вызывает:

alert (lang.date_message);

И это работает, я думаю, очень легко.

0 голосов
/ 28 июня 2014

Мы используем MVC и просто создали действие контроллера для возврата локализованной строки. Мы поддерживаем культуру пользователя в сеансе и устанавливаем культуру потоков перед любым вызовом для извлечения языковой строки, AJAX или иным образом. Это означает, что мы всегда возвращаем локализованную строку.

Я признаю, что это не самый эффективный метод, но получение локализованной строки в javascript редко требуется, поскольку большая часть локализации выполняется в наших частичных представлениях.

Global.asax.cs

protected void Application_PreRequestHandlerExecute(object sender, EventArgs e)
{
    if (Context.Handler is IRequiresSessionState || Context.Handler is IReadOnlySessionState)
    {
        // Set the current thread's culture
        var culture = (CultureInfo)Session["CultureInfo"];
        if (culture != null)
        {
            Thread.CurrentThread.CurrentCulture = culture;
            Thread.CurrentThread.CurrentUICulture = culture;
        }
    }
}

Действие контроллера

public string GetString(string key)
{
    return Language.ResourceManager.GetString(key);
}

Javascript

/*
    Retrieve a localized language string given a lookup key.
    Example use:
      var str = language.getString('MyString');
*/
var language = new function () {
    this.getString = function (key) {
        var retVal = '';
        $.ajax({
            url: rootUrl + 'Language/GetString?key=' + key,
            async: false,
            success: function (results) {
                retVal = results;
            }
        });
        return retVal;
    }
};
...