Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Прочее";
Текущий архив: 2006.05.07;
Скачать: [xml.tar.bz2];

Вниз

Мультиязычность приложения   Найти похожие ветки 

 
tria ©   (2006-04-12 16:20) [0]

Задумался собственно над данной темой.
В голове пока один вариант решения:
1. Создаем текстовый файл с нумерованными строками. Под каждым номерм - собственно текст (заголовки, сообщения).
2. При запуске приложения грузим файл в память в массив.
3. В OnCreate любой формы задаем Caption,Hint всех объектов формы по номеру из массива.
4. В меню приложения делаем пункт language. При его выборе сканируем наличие языковых файлов и собственно предлагаем выбор.

Так вот вопрос. Не велосипед ли я изобретаю? Или все же лучше управляемый ручками велосипед, чем что-то стороннее.
Вопрос возник в свете желания перенести приложение в Лазарус.
Может кто-то поделится своим опытом?


 
isasa ©   (2006-04-12 16:24) [1]

Примерно так-же, только строковые ресурсы хранить в DLL (stringtable), ну и вынимать, соответственно.
Есть, где-то среди примеров "родная", но там сложнее готовить сам текстовый ресурс(нужна сама Дельфи).


 
Игорь Шевченко ©   (2006-04-12 16:25) [2]


> Не велосипед ли я изобретаю?


Его. Называется ресурс, конкретно Stringtable. Насколько я помню, в линуксе мультиязычность уже каким-то образом реализована, не лучше ли посмотреть, каким ?


 
isasa ©   (2006-04-12 16:26) [3]

Да, не уточнил. Для каждого языка, своя DLL. Синхронизация языковых конструкций(во задвинул), по номеру строки.


 
oldman ©   (2006-04-12 16:28) [4]

:)
Можно еще кучу форм состряпать.
Одна по русски, другие по-нерусски.
И FormN.Show в зависимости от выбора языка
:)


 
isasa ©   (2006-04-12 16:40) [5]

oldman ©   (12.04.06 16:28) [4]
Не, ну это сильно наворочено. :)

Кстати, в D для идентификации Контрол<->номер строки ресурса, очень хорошо подходит поле TComponent.Tag: Longint.


 
tria ©   (2006-04-12 16:46) [6]

Почитал немного про Stringtable.
Что-то я не увидел особой выгоды по сравнению с моим способом. В чем выгода хранить тексты в ресурсах по сравнению с отдельным файлом?
Я лично вижу в отдельных файлах такие плюсы:
1. Перевод на другой язык может выполнять любой специалист/пользователь. В том числе и "под себя".
2. Новый язык может быть добавлен без изменения самого приложения.
3. Размер программы не зависит от числа поддерживаемых языков.


 
Игорь Шевченко ©   (2006-04-12 16:50) [7]


> Что-то я не увидел особой выгоды по сравнению с моим способом.
>  В чем выгода хранить тексты в ресурсах по сравнению с отдельным
> файлом?


Ресурсы совмещаются с исполняемым файлом программы, плюс оптимизованный поиск нужной строки по ее идентификатору. Тебе ведь в файле тоже искать надо будет нужную строку ?


 
tria ©   (2006-04-12 16:51) [8]

>Кстати, в D для идентификации Контрол<->номер строки ресурса, очень хорошо подходит поле TComponent.Tag: Longint.

А потом перебрать все контролы формы и присвоить Caption-ы согласно тегам. Одна стандартная процедурина на все формы :)
Только с хинтами проблема. И с другими текстовыми полями.


 
isasa ©   (2006-04-12 16:55) [9]

tria ©   (12.04.06 16:46) [6]
Без проблем. В случае DLL п.2,3 работают.
С п.1 я бы не горячился, есть такие "переводчики"
А вообще, хранение дело рук самого хранящего. Хочешь быть модным - храни в xml. :)


 
tria ©   (2006-04-12 16:55) [10]

>Ресурсы совмещаются с исполняемым файлом программы, плюс оптимизованный поиск нужной строки по ее идентификатору. Тебе ведь в файле тоже искать надо будет нужную строку ?

Простое решение в лоб: массив строк. Правда поиск не по идентификатору, а по номеру. Зато очень просто, быстро и надежно.


 
isasa ©   (2006-04-12 16:58) [11]

tria ©   (12.04.06 16:51) [8]
Так тебе-же доступно RTTI. Смотри тип объекта и, соответственно, заполняй его поля.
if (Component[i] is TEdit) then ...
if (Component[i] is TLabel) then ...


 
tria ©   (2006-04-12 17:01) [12]

>А вообще, хранение дело рук самого хранящего. Хочешь быть модным - храни в xml. :)
Не, я лучше буду использовать маленький такой sql-серверок :).


 
tria ©   (2006-04-12 17:07) [13]

>Так тебе-же доступно RTTI. Смотри тип объекта и, соответственно, заполняй его поля.
if (Component[i] is TEdit) then ...
if (Component[i] is TLabel) then ...

Это понятно. Но тег один на компонент. А текст заголовка и подсказки, чаще всего, отличается.
Разве что завести что-то наподобие двумерного массива. Первая колонка - Caption, вторая - Hint.
Учитывая, что для пустого String уйдет 4 байта (или сколько там), то 2/3 пустых хинтов - это не критично.


 
isasa ©   (2006-04-12 17:07) [14]

:)
Я к чему.
В варианте с DLL(stringtable) ничего делать не надо.
Береш(даешь) у переводчика(у) таблицу - номер строки, русский текст, англ. текст, укр. текст, .... . Выгружаешь в csv-файл с разделителем запятая номер строки и нужную колонку(расширение rc), ствишь в начале
stringtable {
в конце }, компилируешь. Библиотека готова. Перевод сделан сторонним лицом.


 
antonn ©   (2006-04-12 17:13) [15]

inifiles?


 
isasa ©   (2006-04-12 17:18) [16]

antonn ©   (12.04.06 17:13) [15]
Текущий язык и соответствие язык<->имя dll - YES! Или реестр.


 
tria ©   (2006-04-12 17:20) [17]

>inifiles
Да собственно говоря, формировать свой файл в каком-то формате - это же не проблема. Работы на пол дня. И ни с кем ни к чему не привязан, почти полная кросс-платформенность.


 
antonn ©   (2006-04-12 17:22) [18]

isasa ©   (12.04.06 17:18) [16]
Или реестр.

Фу:)
ини-файл может сделать любой, кто с блокнотом работает, куда уж проще:) значит с этой стороны препятствий нет, что способствует переводу сторонних лиц:)


 
antonn ©   (2006-04-12 17:25) [19]

а вообще в одной своей программке я так и делаю:)

> 2. При запуске приложения грузим файл в память в
>массив.
> 3. В OnCreate любой формы задаем Caption,Hint всех
>объектов формы по номеру из массива.
> 4. В меню приложения делаем пункт language. При его
> выборе сканируем наличие языковых файлов и собственно
> предлагаем выбор.


 
Desdechado ©   (2006-04-12 17:54) [20]

мультиязычность подразумевает не только перевод текста, например:
- надписи справа налево
- надписи на картинках
- изобразительная символика
- звуковая символика
- если работа с БД, то предусмотреть возможность перевода данных, недоступных пользователю на редактирование


 
Desdechado ©   (2006-04-12 17:56) [21]

ITE в дельфи, кстати, все это и делает
зачем велосипеды?

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


 
tria ©   (2006-04-12 17:56) [22]

Или еще идея: в Caption, Hint и прочие необходимые строковые поля заносим номер строки в массиве переводов. При открытии перебираемвсе контролы формы и присваиваем перевод согласно указанному номеру.
Полная автоматизация :)
Один минус: нельзя использовать заголовки, содержащие только числа.


 
iZEN_   (2006-04-13 11:38) [23]

Вот ещё одна реализация (данные локалей, русской и английской, хранятся в классе):


public class I18NResources {
   public static final int ID_GAME_NEW = 0;
   public static final int ID_GAME_OPTIONS = 1;
   public static final int ID_GAME_HIGHSCORES = 2;
   public static final int ID_GAME_INSTRUCTIONS = 3;
   public static final int ID_GAME_ABOUT = 4;
   public static final int ID_GAME_CONTINUE = 5;
   public static final int ID_COMMAND_GAME_BACK = 6;
   public static final int ID_COMMAND_GAME_MORE = 7;
   public static final int ID_COMMAND_GAME_EXIT = 8;
   public static final int ID_GAME_LEVEL = 9;
   public static final int ID_GAME_SOUNDS = 10;
   public static final int ID_GAME_VIBRA = 11;
   public static final int ID_GAME_NAME = 12;
   public static final int ID_COMMAND_GAME_START = 13;
   public static final int ID_COMMAND_GAME_PAUSE = 14;
   public static final int ID_COMMAND_SETTINGS_OK = 15;
   public static final int ID_COMMAND_SETTINGS_CANCEL = 16;
   public static final int ID_GAME_SPEED = 17;
   /**
    * Список поддерживаемых локалей.
    * Название локалей специфичны для устройств Nokia
    * и определены в системном свойстве "microedition.locale".
    * Для устройств других производителей названия локалей может не совпадать
    * с представленными, тем не менее метод вывода смягчает этот недостаток.
    */
   private static final String[] supportedLocales = {"en", "ru-RU"};
   /**
    * NOTE: первым представлен список строк языка по умолчанию,
    * метод getString использует его, если не может найти соответствующую локаль.
    * Строки для каждой локали индексированы в соответствии с поддерживаемыми локалями.
    */
   private static final String[][] strings = {
       {"New game", "Settings", "High scores", "Instructions", "About",
           "Continue", "Back", "More", "Exit", "Level", "Sounds", "Shakes",
           "Launch Ball!", "Start", "Pause", "OK", "Cancel", "Speed"},
       {"Новая игра", "Установки", "Рекорды", "Справка", "О программе",
           "Продолжить", "Назад", "Далее", "Выход", "Уровень", "Звук",
           "Вибра", "Запусти шарик!", "Старт", "Пауза", "ОК", "Отмена",
           "Скорость"}};
   /**
    * Возвращает строку, соответствующую ключу.
    * @param ключ типа Integer для строки
    * @return строка
    */
   public static String getString(int key) {
       String locale = System.getProperty("microedition.locale");
       //System.out.println("microedition.locale = " + locale);
       if (locale == null) {
           locale = "en";//принимается по умолчанию
       }
       /* поиск индекса соответствия локали */
       int localeIndex = -1;
       for (int i = 0; i < supportedLocales.length; i++) {
           /* if (locale.equals(supportedLocales[i])) {
            * - это НЕ работает на некоторых устройствах.
            * Поэтому лучше так:
            */
           if (supportedLocales[i].startsWith(locale)) {
               localeIndex = i;
               break;
           }
       }
       /*  если не найдена подходящая локаль, используется первая из списка  */
       if (localeIndex == -1) { return strings[0][key]; }
       return strings[localeIndex][key];
   }
}

Использование:

public class SettingsForm extends Form {
//...
   /**
    * Конструктор без параметров.
    */
   public SettingsForm() {
       super(I18NResources.getString(I18NResources.ID_GAME_OPTIONS));
       this.okCommand = new Command(I18NResources.getString(I18NResources.ID_COMMAND_SETTINGS_OK), Command.OK, 1);
       this.cancelCommand = new Command(I18NResources.getString(I18NResources.ID_COMMAND_SETTINGS_CANCEL), Command.CANCEL, 2);
       this.addCommand(okCommand);
       this.addCommand(cancelCommand);
       score = new Gauge(I18NResources.getString(I18NResources.ID_GAME_SPEED), true, Ball.SCORE_MAX, Ball.SCORE_MIN);
       this.append(score);
   }
//...


А вообще экономически выгодно хранить локализацию в отдельных текстовых файлах (ресурсах) и подгружать только то, что будет использоваться (может зависеть как от локализации операционной системы, так и выбора пользователя).

Главное хранилище имеет ассоциативную структуру (Хэш-таблица, которая может быть реализована массивом): целочисленный_идентификатор -> название_на_выбранном_языке.
Чтобы не путаться, целочисленный_идентификатор имеет вполне "человеческое" имя.



Страницы: 1 вся ветка

Форум: "Прочее";
Текущий архив: 2006.05.07;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.53 MB
Время: 0.012 c
3-1141891899
Shura
2006-03-09 11:11
2006.05.07
Ошибка при удалении записи в ClientDataSet


2-1145590311
Holod
2006-04-21 07:31
2006.05.07
хм...


15-1144937234
ArtemESC
2006-04-13 18:07
2006.05.07
Объясните тупому на примере ,пожалуйста, ...


15-1144419181
DelphiLexx
2006-04-07 18:13
2006.05.07
Как в Delphi 2005 установить компонент


15-1144829765
user026
2006-04-12 12:16
2006.05.07
Где найти документацию по формату хранения типов данных в памяти





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский