Просмотр полной версии : Два языка меню в XML
Добрый день
В проекте у меня все текста подгружаются с XML. Перед началом запуска планирую ввести опцию на 2 языка.
Скажите, как можно объединить оба языка в одной xml?
Вот пример структуры
<<content>
<menu>
<but1>
<RU>btn1</RU>
<EN>btn1</EN>
</but1>
<but2>
<RU>btn2</RU>
<EN>btn2</EN>
</but2>
</menu>
</content>
Как мне в AS3 указать, какие теги считывать в зависимости от выбранного языка? То есть при выброанном русском в каждом теге кнопок считывать только RU
Если Вы знаете как получить xml.menu.but1, то наверняка догадываетесь, как получать xml.menu.but1.RU
Значит, загвоздка в чем-то другом. Вы готовы сформулировать вопрос не в стиле Битвы Экстрасенсов?
Видимо для этого надо перейти на 4 уровень посвящения
Так, попробую объяснить.
Идея заключалась в том, чтобы облегчить код, и не делать проверку во всех заполнениях в текстовых поля, какой сейчас режим - русский или английский.
То есть чтобы выглядело просто как
var text:TextField = new TextField();
text.text = xml.main_menu.btn1; // без дополнительных RU/EN в проверках
Может есть какой то вариант при загрузке xml распихать все теги(можно переделать в атрибуты кстати) с RU в такой же иерархии и дать этому свой ruXML, и соответственно enXML, а при смене языков присваивать xml значение или ruXML или enXML
<content>
<menu>
<but1 rus="Кноп1" eng="btn1" />
<but2 rus="Кноп2" eng="btn2" />
</menu>
</content>
Если у Вас переключение языка может происходить в любой момент, то все-равно придется делать менеджер,
регистрирующий все лейблы и производящий обновление когда потребуется. Не могут лейблы сами спрашивать, какой сейчас язык.
Им пришлось бы спрашивать это на каждый enterFrame.
Wolsh ну да, понятно что надо будет запускать функцию update на текста, но опять же, тут надо будет делать проверку
Не очень понимаю, что Вас страшит.. Ну сделайте в XML два больших блока RUS и ENG — фактически два XML в одном файле. Внутри блоков будет совершенно одинаковая структура, и менеджер будет просто брать из нее жесткие данные. Все что надо ему сказать — какой сейчас язык, из какого блока брать данные.
LangSwitcher.swf
package
{
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.events.MouseEvent;
import ru.wolsh.testware.button.GreenButton;
import ru.wolsh.testware.button.RedButton;
import ru.wolsh.testware.text.Label;
/**
* ...
* @author wolsh
*/
public class Main extends Sprite
{
private var _labels:Array;
private var _language:String = "rus";
private var _xml:XML;
public function Main():void
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
// entry point
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;
_xml =
<content>
<menu>
<but1 rus="Кнопка 1" eng="Button 1" />
<but2 rus="Кнопка 2" eng="Button 2" />
</menu>
</content>
var lab1:Label = new Label(_xml.menu.but1.@rus);
lab1.name = "but1";
var b1:GreenButton = new GreenButton(lab1, 120, 36, [4,4,4,4]);
this.addChild(b1);
b1.x = 100;
b1.y = 100;
var lab2:Label = new Label(_xml.menu.but2.@rus);
lab2.name = "but2";
var b2:GreenButton = new GreenButton(lab2, 120, 36, [4,4,4,4]);
this.addChild(b2);
b2.x = 100;
b2.y = 150;
_labels = [lab1, lab2]; // Примитивная "регистрация" лейблов в "менеджере"
var b3:RedButton = new RedButton(new Label("Рус / Eng"), 120, 36, [4, 4, 4, 4]);
this.addChild(b3);
b3.x = 300;
b3.y = 100;
b3.addEventListener(MouseEvent.CLICK, handlerLangClick);
}
private function handlerLangClick(event:MouseEvent):void
{
_language = _language == "rus" ? "eng" : "rus";
for each(var lab:Label in _labels)
{
lab.text = _xml.menu[lab.name].@[_language];
}
}
}
}
спасибо, я конечно представлял это еще попроще, через обычную передачу значения в функцию update..
что же, буду делать тогда так
mikhailk
11.04.2013, 12:46
А что мешает иметь два отдельных файла contentRu.xml и contentEn.xml?
Жизнь сразу становится легка и комфортна.
mikhailk
я так и делал раньше, но заполнять все по пунктам на 2-ух языках сразу легче, чем теже пункты в двух файлах. Структура то не из 4 кнопок состоит
mikhailk
11.04.2013, 13:08
я так и делал раньше, но заполнять все по пунктам на 2-ух языках сразу легче, чем теже пункты в двух файлах. Структура то не из 4 кнопок состоит
Еще вот так можно:
<content>
<menu>
<but ID="but1" lang="ru">Рус</but>
<but ID="but1" lang="en">Eng</but>
<but ID="but2" lang="ru">Рус2</but>
<but ID="but2" lang="en">Eng2</but>
</menu>
</content>
Доставать, соответственно, так:
public function getBtnLabel(btnID:String,currentLang:String) : String
{
return String(content.menu.but.(@ID=btnID&&@lang=currenLang));
}
Спасибо всем за отзыв!
сделал все таки структуру по тегам, а язык сменяется по 2-ум атрибутам. В моем случае самое удобное, просто в функции update на текстовые поля передается выбранный язык
не мог бы кто-нибудь пояснить, почему для смены языка лучше использовать xml, а не массив в синглтоне? Так удобнее или быстрее или ещё какие-то причины?
mikhailk
10.02.2014, 10:41
Нужно отделить контент от кода. Языковой файл как правило текстовый и доступный для ручного заполнения, но желательно с какой-нибудь более-менее регулярной структурой. XML - вполне себе вариант, но сейчас бы я порекомендовал YAML.
При отделении контента от кода возникает вопрос, не плохо ли для производительности постоянное обращение к внешнему файлу?
К тому же, никак не пойму, как создать внешний xml для редактирования и потом к нему обращаться?
Например, что происходит, когда мы пишем следующее?:Xml =
<content>
<menu>
<text rus='Русский' eng='English' />
</menu>
</content>
Создаётся файл xml? В папках я найти его не могу. Или он создаётся как-то "внутри"?
Поясните, пожалуйста, или посоветуйте, что почитать для прояснения вопроса.
mikhailk
10.02.2014, 13:29
При отделении контента от кода возникает вопрос, не плохо ли для производительности постоянное обращение к внешнему файлу?
Нет никакого обращения к внешнему файлу. Языковой файл эмбеддится в проект или грузится на старте вместе с остальными ресурсами.
На самом деле, в приложении должен быть некоторый класс, который отвечает за предоставление конкретных шаблонов фраз в соответствии с контекстом, и xml-файл или другой файл данных служит для ввода данных в систему. Дальше все на совести программиста. Либо этот класс выдачи фраз лазит в файл, либо хранит в собственном массиве - кому как удобно.
Создаётся файл xml?
Создается объект типа XML.
Почитать можно тут:
http://help.adobe.com/ru_RU/FlashPlatform/reference/actionscript/3/XML.html
Я завёл класс Lang, отвечающий за тексты и переключение языка:
package RC {
public class Lang {
public static var xml:XML =
<content>
<menu>
<text rus='Русский текст в меню' eng='English text in the menu' />
</menu>
<level>
<text rus='Русский текст в уровне' eng='English text in the level' />
</level>
</content>;
public static var lang:String = 'eng';
};
};
Проверил с помощью
trace(Lang.xml.menu.text.attribute(Lang.lang));
trace(Lang.xml.level.text.attribute(Lang.lang));
Выводит то, что надо, даже \n работает!
Выходит, что таким образом можно будет в любой момент менять язык, меняя Lang.lang с 'rus' на 'eng' и наоборот. Осталось только напихать в переменную xml узлов, отвечающих за другие комнаты и тексты. Скажите, пожалуйста, целесообразен ли такой подход?
И ещё, атрибуты, вроде, можно писать как @* вместо attribute(*), но для переключения атрибутов приходится использовать строковое значение, которое можно вставить только в скобки к attribute(). Можно это как-то сократить, чтобы использовать всё же конструкцию с @?
Я бы тоже не использовал структуру автора. Ее сложно расширять.
Сделал ещё проще:
Класс Lang.as:
package {
public class Lang {
public static const Eng:XML =
<texts>
<menu
title='MENU'
/>
</texts>;
public static const Rus:XML =
<texts>
<menu
title='МЕНЮ'
/>
</texts>;
public static var language:String = 'eng';
};
};
В комнате-спрайте, где будут дети с текстом, свойству
private var _lang:XMLList;
присваиваем при инициализации значение, зависящее от того, какой установлен язык (Rus или Eng) и что это за комната (в данном примере - menu):
_lang = (Lang.language == 'eng')?(Lang.Eng.menu):(Lang.Rus.menu);
Проверяем: trace('Menu title: '+_lang.@title) // выводит 'MENU', если включен английский и "МЕНЮ", если русский
Насколько я понял, примерно такую схему имел в виду Wolsh в сообщении №7: 2 идентичных блока, один на русском, другой на английском. При инициализации "комнаты" определяется, из какого блока брать текст. Таким образом, даже если нужно будет внезапно поменять язык, достаточно присвоить переменной _lang соответствующее значение и обновить все тексты.
Буду признателен, если знающие люди подскажут, что плохого в описанной выше схеме или всё ок?
mikhailk
10.02.2014, 16:04
Я бы обратил внимание на реплику GBee:
сложно расширять.
Делать можно как угодно, но перед тем, как принимать окончательное решение надо ответить на этот простой вопрос:
- удобно ли мне потом будет расширять функционал, если потребуется (новые разделы, расширение существующих разделов, новые языки)
И еще, по моему личному опыту - перевод на английский (например) язык делает как правило другой человек. Поэтому удобно, когда 1 язык = 1 файл.
я учту, спасибо. Тема для меня новая, поэтому к универсальности конструкций (т.е. удобству их редактирования в будущем) я прийду позже. Пока же интересно, насколько хороша система, на которой я решил остановиться на данный момент, в плане быстродействия приложения и отсутствия ошибок.
Работает на vBulletin ® версия 3.7.3. Copyright ©2000-2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Copyright © 1999-2008 Flasher.ru. All rights reserved.