Главная > Flex > Простая локализация Flex приложений

Простая локализация Flex приложений

Рано или подзно перед разработчиком встает задача локализации приложения. На самом деле сделать это очень просто, но и тут есть свои подводные камни. Итак, обо всем по порядку.

Как создать новую локаль?

По умолчанию Flex поддерживает две локали — английскую и японскую (en_US, jp_JP). Предположим вам необходимо обеспечить поддержку немецкой локали de_DE. Вам придется создать ее самостоятельно:

1) Запускаем командную строку от имени администратора.

2) Переходим в папку установки Flex SDK, в директорию bin (в моем случае это C:\Program Files\Adobe\Flex Builder 3\sdks\3.0.0\bin\) и находим утилиту copylocale.exe
Запускаем ее следующим образом:
copylocale en_US de_DE

3) Переходим в папку с локалями, чтобы убедиться в успешности операции. В моем случае это C:\Program Files\Adobe\Flex Builder 3\sdks\3.0.0\frameworks\locale\
Там должна появиться новая папка de_DE и в ней набор swc-файлов. Готово!

Выкладываю свою версию немецкой локали (Flex SDK 3.0.0), скачать ее можно тут.

Примечание: мой архив включает datavisualization_rb.swc, который необходим для работы некоторых компонентов Flex.

Создаем мультиязычный проект

Итак вы подготовили проект и создали, теперь займемся непосредственно локализацией. В корне проекта создайте папку locale в которую поместите папки с названием используемых локалей в приложении, например создайте en_US и de_DE. Переводы мы будем хранить в так называемых .properies файлах. У вас должна в итоге получиться структура похожая на мою:

translations

Я создал translations.properies файл для каждой локали. Синтаксис этих файлов предельно прост — записываем туда пары

КЛЮЧ = ЗНАЧЕНИЕ (строка)

или

КЛЮЧ = ЗНАЧЕНИЕ_1, ЗНАЧЕНИЕ_2, ..., ЗНАЧЕНИЕ_N. (массив)

каждую с новой строки. Файлы необходимо сохранять в кодировке UTF-8. Итак внесем в наши файлы переводы.

en_US:

CANCEL = Cancel
SAVE = Save
FIELD_IS_REQUIRED = This field is required

de_DE:

CANCEL = Abbrechen
SAVE = Speichern
FIELD_IS_REQUIRED = Pflichtfeld

И последний, но немаловажный штрих — настройка компилятора. Добавьте следующие аргументы компилятора в свой проект (в среде Flex Builder это делается по правому клику на проекте Properties -> Flex Library Compiler -> Additional Compiler Arguments):

-locale de_DE en_US -source-path+=../locale/{locale}

При таких аругментах компилятора локалью по умолчанию будет de_DE.

Класс Translator

Создадим класс Translator для инкапсуляции наших переводов.

package ru.flexdev.utils
{
	import mx.resources.ResourceManager;
 
	public class Translator 
	{
		[ResourceBundle("translations")]
		public static const TRANSLATIONS_RESOURCE:String = 'translations';
 
		public static function getString(name:String):String 
		{
			var result:String = ResourceManager.getInstance().getString(TRANSLATIONS_RESOURCE, name);
			return result ? result : name;
		}
 
                public static function getStringArray(name:String):Array {
			var result:Array = ResourceManager.getInstance().getStringArray(TRANSLATIONS_RESOURCE, name);
			return result ? result : name;	
		}
	}
}

Теперь мы можем пользоваться переводами в UI. Например:

<mx:Button label="{Translator.getString('CANCEL')}" />

Заключение

В заключении хочу добавить несколько моментов по поводу синтаксиса .properties файлов.
1) Стандарта нет, но я для себя создал правило записывать ключи в верхнем регистре, как константы.
2) Как я уже сказал — файлы должны быть сохранены в кодировке UTF-8, но можно этого и не делать, а просто заменять в тексте UTF-символы их кодами, например для de_DE:

A-umlaut: \u00E4
O-umlaut: \u00F6
U-umlaut: \u00FC
double S: \u00DF

3) Текущую локаль приложения я обычно передаю через flashvars во Flex и устанавливаю при инициализации приложения так:

private function init():void
{
    // set up locale
    var localeChain:Array = ["de_DE", "en_US"];
    var locale:String = Application.application.parameters.localeString;
    if(localeChain.indexOf(locale) > -1) {
        resourceManager.localeChain = [locale];
    }
    else {
        resourceManager.localeChain = localeChain;
    }
    // startup
    ...
}

Надеюсь получилось не слишком запутано, если что-то не ясно — я отвечу на адекватные вопросы по теме статьи.

Flex , ,

  1. 20 Июль 2009 из 20:22 | #1

    Отличная статья.

    Недостатоки этого метода:

    — нельзя менять язык в runtime

    — для изменения значения строк нужно пересобирать приложение

    — а следовательно пользователь не может сам добавить новый язык

    Это ни в коем случае не фатально — просто надо иметь в виду.

  2. 21 Июль 2009 из 11:20 | #2

    Спасибо!

    Верно подмечено на счёт того что каждый раз приходится пересобирать приложение. А вот язык в рантайме менять нам ничего не мешает.

    Это один из способов локализации, думаю, в дальнейшем можно будет привести и другие примеры.

  3. 21 Июль 2009 из 12:57 | #3

    По поводу этой конструкции:

    ... label="{Translator.getString ('CANCEL')}" ...

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

    Там есть еще особенности:

    — Название функции сокращено до предела, выглядит так: t ('Cancel');

    — Строки автоматически собираются фреймворком по всему коду во всех файлах и выносятся в файл языка автоматически. Это позволяет отказаться от использования констант, а писать непосредственно строковые значения.

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

    И, возможно, есть смысл попробовать такой подход во Flex, как вы считаете?

    За статью спасибо, очень понятно написано, просто бери и локализуй все, что написал :)

  4. 21 Июль 2009 из 15:19 | #4

    Как же — не мешает? У вас в примере label="{Translator.getString ('CANCEL')}" — функция getString статическая, а следовательно в принципе не может диспатчить событие и менять тексты при смене языка.

    Единственный вариант — пересоздать при этом весь UI.

  5. 23 Июль 2009 из 0:11 | #5

    во, подпишусь на тебя:) азадачился изучением флэш со вчерашнего дня. с интерфейсом flash cs4 разобрался, теперь разбираюсь с актионскриптом, синтаксис сам понятен, но до компиляции хелло ворда не дошел=)

    а теперь вопрос, чем отлечается флэкс от того чтодает flash cs4? и flex и flash будут откомпелированые везде работать одинаково? стоит ли сразу учить flex?

    задачи сейчас не большие но они расширятся на большой уровень.

    т.к. делаю игру которая модульная, т.е. фичи игры дописываются легко.

  6. 23 Июль 2009 из 16:19 | #6

    Совершенно верно, придётся пересоздать UI, но язык, а точнее локаль, нам ничего не мешает менять «на лету» :)

  7. 23 Июль 2009 из 16:24 | #7

    Гвест :

    а теперь вопрос, чем отлечается флэкс от того чтодает flash cs4? и flex и flash будут откомпелированые везде работать одинаково? стоит ли сразу учить flex?

    Будет очень полезно выучить обе технологии. О различиях можно прочитать в википедии

    ru.wikipedia.org/wiki/Adobe_Flash и ru.wikipedia.org/wiki/Adobe_Flex

  1. Трекбеков пока нет.