PDA

Просмотр полной версии : Два языка меню в XML


pomuс
10.04.2013, 19:50
Добрый день

В проекте у меня все текста подгружаются с 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

Wolsh
10.04.2013, 21:36
Если Вы знаете как получить xml.menu.but1, то наверняка догадываетесь, как получать xml.menu.but1.RU
Значит, загвоздка в чем-то другом. Вы готовы сформулировать вопрос не в стиле Битвы Экстрасенсов?

Babylon
10.04.2013, 21:49
Видимо для этого надо перейти на 4 уровень посвящения

pomuс
10.04.2013, 22:01
Так, попробую объяснить.
Идея заключалась в том, чтобы облегчить код, и не делать проверку во всех заполнениях в текстовых поля, какой сейчас режим - русский или английский.
То есть чтобы выглядело просто как
var text:TextField = new TextField();
text.text = xml.main_menu.btn1; // без дополнительных RU/EN в проверках

Может есть какой то вариант при загрузке xml распихать все теги(можно переделать в атрибуты кстати) с RU в такой же иерархии и дать этому свой ruXML, и соответственно enXML, а при смене языков присваивать xml значение или ruXML или enXML

Wolsh
10.04.2013, 22:24
<content>
<menu>
<but1 rus="Кноп1" eng="btn1" />
<but2 rus="Кноп2" eng="btn2" />
</menu>
</content>
Если у Вас переключение языка может происходить в любой момент, то все-равно придется делать менеджер,
регистрирующий все лейблы и производящий обновление когда потребуется. Не могут лейблы сами спрашивать, какой сейчас язык.
Им пришлось бы спрашивать это на каждый enterFrame.

pomuс
10.04.2013, 22:36
Wolsh ну да, понятно что надо будет запускать функцию update на текста, но опять же, тут надо будет делать проверку

Wolsh
10.04.2013, 22:51
Не очень понимаю, что Вас страшит.. Ну сделайте в XML два больших блока RUS и ENG — фактически два XML в одном файле. Внутри блоков будет совершенно одинаковая структура, и менеджер будет просто брать из нее жесткие данные. Все что надо ему сказать — какой сейчас язык, из какого блока брать данные.

Wolsh
10.04.2013, 23:28
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];
}
}
}
}

pomuс
11.04.2013, 11:27
спасибо, я конечно представлял это еще попроще, через обычную передачу значения в функцию update..
что же, буду делать тогда так

mikhailk
11.04.2013, 12:46
А что мешает иметь два отдельных файла contentRu.xml и contentEn.xml?
Жизнь сразу становится легка и комфортна.

pomuс
11.04.2013, 12:50
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));
}

pomuс
11.04.2013, 23:23
Спасибо всем за отзыв!
сделал все таки структуру по тегам, а язык сменяется по 2-ум атрибутам. В моем случае самое удобное, просто в функции update на текстовые поля передается выбранный язык

a7s1h1
10.02.2014, 10:26
не мог бы кто-нибудь пояснить, почему для смены языка лучше использовать xml, а не массив в синглтоне? Так удобнее или быстрее или ещё какие-то причины?

mikhailk
10.02.2014, 10:41
Нужно отделить контент от кода. Языковой файл как правило текстовый и доступный для ручного заполнения, но желательно с какой-нибудь более-менее регулярной структурой. XML - вполне себе вариант, но сейчас бы я порекомендовал YAML.

a7s1h1
10.02.2014, 13:23
При отделении контента от кода возникает вопрос, не плохо ли для производительности постоянное обращение к внешнему файлу?
К тому же, никак не пойму, как создать внешний 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

a7s1h1
10.02.2014, 14:31
Я завёл класс 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(). Можно это как-то сократить, чтобы использовать всё же конструкцию с @?

GBee
10.02.2014, 15:18
Я бы тоже не использовал структуру автора. Ее сложно расширять.

a7s1h1
10.02.2014, 15:42
Сделал ещё проще:
Класс 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 файл.

a7s1h1
10.02.2014, 16:33
я учту, спасибо. Тема для меня новая, поэтому к универсальности конструкций (т.е. удобству их редактирования в будущем) я прийду позже. Пока же интересно, насколько хороша система, на которой я решил остановиться на данный момент, в плане быстродействия приложения и отсутствия ошибок.