123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705 |
- /*************************************************************************/
- /* translation.cpp */
- /*************************************************************************/
- /* This file is part of: */
- /* GODOT ENGINE */
- /* http://www.godotengine.org */
- /*************************************************************************/
- /* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
- /* */
- /* Permission is hereby granted, free of charge, to any person obtaining */
- /* a copy of this software and associated documentation files (the */
- /* "Software"), to deal in the Software without restriction, including */
- /* without limitation the rights to use, copy, modify, merge, publish, */
- /* distribute, sublicense, and/or sell copies of the Software, and to */
- /* permit persons to whom the Software is furnished to do so, subject to */
- /* the following conditions: */
- /* */
- /* The above copyright notice and this permission notice shall be */
- /* included in all copies or substantial portions of the Software. */
- /* */
- /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
- /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
- /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
- /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
- /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
- /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
- /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
- /*************************************************************************/
- #include "translation.h"
- #include "globals.h"
- #include "io/resource_loader.h"
- #include "os/os.h"
- static const char* locale_list[]={
- "ar", // Arabic
- "ar_AE", // Arabic (United Arab Emirates)
- "ar_BH", // Arabic (Bahrain)
- "ar_DZ", // Arabic (Algeria)
- "ar_EG", // Arabic (Egypt)
- "ar_IQ", // Arabic (Iraq)
- "ar_JO", // Arabic (Jordan)
- "ar_KW", // Arabic (Kuwait)
- "ar_LB", // Arabic (Lebanon)
- "ar_LY", // Arabic (Libya)
- "ar_MA", // Arabic (Morocco)
- "ar_OM", // Arabic (Oman)
- "ar_QA", // Arabic (Qatar)
- "ar_SA", // Arabic (Saudi Arabia)
- "ar_SD", // Arabic (Sudan)
- "ar_SY", // Arabic (Syria)
- "ar_TN", // Arabic (Tunisia)
- "ar_YE", // Arabic (Yemen)
- "be", // Belarusian
- "be_BY", // Belarusian (Belarus)
- "bg", // Bulgarian
- "bg_BG", // Bulgarian (Bulgaria)
- "ca", // Catalan
- "ca_ES", // Catalan (Spain)
- "cs", // Czech
- "cs_CZ", // Czech (Czech Republic)
- "da", // Danish
- "da_DK", // Danish (Denmark)
- "de", // German
- "de_AT", // German (Austria)
- "de_CH", // German (Switzerland)
- "de_DE", // German (Germany)
- "de_LU", // German (Luxembourg)
- "el", // Greek
- "el_CY", // Greek (Cyprus)
- "el_GR", // Greek (Greece)
- "en", // English
- "en_AU", // English (Australia)
- "en_CA", // English (Canada)
- "en_GB", // English (United Kingdom)
- "en_IE", // English (Ireland)
- "en_IN", // English (India)
- "en_MT", // English (Malta)
- "en_NZ", // English (New Zealand)
- "en_PH", // English (Philippines)
- "en_SG", // English (Singapore)
- "en_US", // English (United States)
- "en_ZA", // English (South Africa)
- "es", // Spanish
- "es_AR", // Spanish (Argentina)
- "es_BO", // Spanish (Bolivia)
- "es_CL", // Spanish (Chile)
- "es_CO", // Spanish (Colombia)
- "es_CR", // Spanish (Costa Rica)
- "es_DO", // Spanish (Dominican Republic)
- "es_EC", // Spanish (Ecuador)
- "es_ES", // Spanish (Spain)
- "es_GT", // Spanish (Guatemala)
- "es_HN", // Spanish (Honduras)
- "es_MX", // Spanish (Mexico)
- "es_NI", // Spanish (Nicaragua)
- "es_PA", // Spanish (Panama)
- "es_PE", // Spanish (Peru)
- "es_PR", // Spanish (Puerto Rico)
- "es_PY", // Spanish (Paraguay)
- "es_SV", // Spanish (El Salvador)
- "es_US", // Spanish (United States)
- "es_UY", // Spanish (Uruguay)
- "es_VE", // Spanish (Venezuela)
- "et", // Estonian
- "et_EE", // Estonian (Estonia)
- "fi", // Finnish
- "fi_FI", // Finnish (Finland)
- "fr", // French
- "fr_BE", // French (Belgium)
- "fr_CA", // French (Canada)
- "fr_CH", // French (Switzerland)
- "fr_FR", // French (France)
- "fr_LU", // French (Luxembourg)
- "ga", // Irish
- "ga_IE", // Irish (Ireland)
- "hi", // Hindi (India)
- "hi_IN", // Hindi (India)
- "hr", // Croatian
- "hr_HR", // Croatian (Croatia)
- "hu", // Hungarian
- "hu_HU", // Hungarian (Hungary)
- "in", // Indonesian
- "in_ID", // Indonesian (Indonesia)
- "is", // Icelandic
- "is_IS", // Icelandic (Iceland)
- "it", // Italian
- "it_CH", // Italian (Switzerland)
- "it_IT", // Italian (Italy)
- "iw", // Hebrew
- "iw_IL", // Hebrew (Israel)
- "ja", // Japanese
- "ja_JP", // Japanese (Japan)
- "ja_JP_JP", // Japanese (Japan,JP)
- "ko", // Korean
- "ko_KR", // Korean (South Korea)
- "lt", // Lithuanian
- "lt_LT", // Lithuanian (Lithuania)
- "lv", // Latvian
- "lv_LV", // Latvian (Latvia)
- "mk", // Macedonian
- "mk_MK", // Macedonian (Macedonia)
- "ms", // Malay
- "ms_MY", // Malay (Malaysia)
- "mt", // Maltese
- "mt_MT", // Maltese (Malta)
- "nl", // Dutch
- "nl_BE", // Dutch (Belgium)
- "nl_NL", // Dutch (Netherlands)
- "no", // Norwegian
- "no_NO", // Norwegian (Norway)
- "no_NO_NY", // Norwegian (Norway,Nynorsk)
- "pl", // Polish
- "pl_PL", // Polish (Poland)
- "pt", // Portuguese
- "pt_BR", // Portuguese (Brazil)
- "pt_PT", // Portuguese (Portugal)
- "ro", // Romanian
- "ro_RO", // Romanian (Romania)
- "ru", // Russian
- "ru_RU", // Russian (Russia)
- "sk", // Slovak
- "sk_SK", // Slovak (Slovakia)
- "sl", // Slovenian
- "sl_SI", // Slovenian (Slovenia)
- "sq", // Albanian
- "sq_AL", // Albanian (Albania)
- "sr", // Serbian
- "sr_BA", // Serbian (Bosnia and Herzegovina)
- "sr_CS", // Serbian (Serbia and Montenegro)
- "sr_ME", // Serbian (Montenegro)
- "sr_RS", // Serbian (Serbia)
- "sv", // Swedish
- "sv_SE", // Swedish (Sweden)
- "th", // Thai
- "th_TH", // Thai (Thailand)
- "th_TH_TH", // Thai (Thailand,TH)
- "tr", // Turkish
- "tr_TR", // Turkish (Turkey)
- "uk", // Ukrainian
- "uk_UA", // Ukrainian (Ukraine)
- "vi", // Vietnamese
- "vi_VN", // Vietnamese (Vietnam)
- "zh", // Chinese
- "zh_CN", // Chinese (China)
- "zh_HK", // Chinese (Hong Kong)
- "zh_SG", // Chinese (Singapore)
- "zh_TW", // Chinese (Taiwan)
- 0
- };
- static const char* locale_names[]={
- "Arabic",
- "Arabic (United Arab Emirates)",
- "Arabic (Bahrain)",
- "Arabic (Algeria)",
- "Arabic (Egypt)",
- "Arabic (Iraq)",
- "Arabic (Jordan)",
- "Arabic (Kuwait)",
- "Arabic (Lebanon)",
- "Arabic (Libya)",
- "Arabic (Morocco)",
- "Arabic (Oman)",
- "Arabic (Qatar)",
- "Arabic (Saudi Arabia)",
- "Arabic (Sudan)",
- "Arabic (Syria)",
- "Arabic (Tunisia)",
- "Arabic (Yemen)",
- "Belarusian",
- "Belarusian (Belarus)",
- "Bulgarian",
- "Bulgarian (Bulgaria)",
- "Catalan",
- "Catalan (Spain)",
- "Czech",
- "Czech (Czech Republic)",
- "Danish",
- "Danish (Denmark)",
- "German",
- "German (Austria)",
- "German (Switzerland)",
- "German (Germany)",
- "German (Luxembourg)",
- "Greek",
- "Greek (Cyprus)",
- "Greek (Greece)",
- "English",
- "English (Australia)",
- "English (Canada)",
- "English (United Kingdom)",
- "English (Ireland)",
- "English (India)",
- "English (Malta)",
- "English (New Zealand)",
- "English (Philippines)",
- "English (Singapore)",
- "English (United States)",
- "English (South Africa)",
- "Spanish",
- "Spanish (Argentina)",
- "Spanish (Bolivia)",
- "Spanish (Chile)",
- "Spanish (Colombia)",
- "Spanish (Costa Rica)",
- "Spanish (Dominican Republic)",
- "Spanish (Ecuador)",
- "Spanish (Spain)",
- "Spanish (Guatemala)",
- "Spanish (Honduras)",
- "Spanish (Mexico)",
- "Spanish (Nicaragua)",
- "Spanish (Panama)",
- "Spanish (Peru)",
- "Spanish (Puerto Rico)",
- "Spanish (Paraguay)",
- "Spanish (El Salvador)",
- "Spanish (United States)",
- "Spanish (Uruguay)",
- "Spanish (Venezuela)",
- "Estonian",
- "Estonian (Estonia)",
- "Finnish",
- "Finnish (Finland)",
- "French",
- "French (Belgium)",
- "French (Canada)",
- "French (Switzerland)",
- "French (France)",
- "French (Luxembourg)",
- "Irish",
- "Irish (Ireland)",
- "Hindi (India)",
- "Hindi (India)",
- "Croatian",
- "Croatian (Croatia)",
- "Hungarian",
- "Hungarian (Hungary)",
- "Indonesian",
- "Indonesian (Indonesia)",
- "Icelandic",
- "Icelandic (Iceland)",
- "Italian",
- "Italian (Switzerland)",
- "Italian (Italy)",
- "Hebrew",
- "Hebrew (Israel)",
- "Japanese",
- "Japanese (Japan)",
- "Japanese (Japan JP)",
- "Korean",
- "Korean (South Korea)",
- "Lithuanian",
- "Lithuanian (Lithuania)",
- "Latvian",
- "Latvian (Latvia)",
- "Macedonian",
- "Macedonian (Macedonia)",
- "Malay",
- "Malay (Malaysia)",
- "Maltese",
- "Maltese (Malta)",
- "Dutch",
- "Dutch (Belgium)",
- "Dutch (Netherlands)",
- "Norwegian",
- "Norwegian (Norway)",
- "Norwegian (Norway Nynorsk)",
- "Polish",
- "Polish (Poland)",
- "Portuguese",
- "Portuguese (Brazil)",
- "Portuguese (Portugal)",
- "Romanian",
- "Romanian (Romania)",
- "Russian",
- "Russian (Russia)",
- "Slovak",
- "Slovak (Slovakia)",
- "Slovenian",
- "Slovenian (Slovenia)",
- "Albanian",
- "Albanian (Albania)",
- "Serbian",
- "Serbian (Bosnia and Herzegovina)",
- "Serbian (Serbia and Montenegro)",
- "Serbian (Montenegro)",
- "Serbian (Serbia)",
- "Swedish",
- "Swedish (Sweden)",
- "Thai",
- "Thai (Thailand)",
- "Thai (Thailand TH)",
- "Turkish",
- "Turkish (Turkey)",
- "Ukrainian",
- "Ukrainian (Ukraine)",
- "Vietnamese",
- "Vietnamese (Vietnam)",
- "Chinese",
- "Chinese (China)",
- "Chinese (Hong Kong)",
- "Chinese (Singapore)",
- "Chinese (Taiwan)",
- 0
- };
- Vector<String> TranslationServer::get_all_locales() {
- Vector<String> locales;
- const char **ptr=locale_list;
- while (*ptr) {
- locales.push_back(*ptr);
- ptr++;
- }
- return locales;
- }
- Vector<String> TranslationServer::get_all_locale_names(){
- Vector<String> locales;
- const char **ptr=locale_names;
- while (*ptr) {
- locales.push_back(*ptr);
- ptr++;
- }
- return locales;
- }
- static bool is_valid_locale(const String& p_locale) {
- const char **ptr=locale_list;
- while (*ptr) {
- if (p_locale==*ptr)
- return true;
- ptr++;
- }
- return false;
- }
- DVector<String> Translation::_get_messages() const {
- DVector<String> msgs;
- msgs.resize(translation_map.size()*2);
- int idx=0;
- for (const Map<StringName, StringName>::Element *E=translation_map.front();E;E=E->next()) {
- msgs.set(idx+0,E->key());
- msgs.set(idx+1,E->get());
- idx+=2;
- }
- return msgs;
- }
- DVector<String> Translation::_get_message_list() const {
- DVector<String> msgs;
- msgs.resize(translation_map.size());
- int idx=0;
- for (const Map<StringName, StringName>::Element *E=translation_map.front();E;E=E->next()) {
- msgs.set(idx,E->key());
- idx+=1;
- }
- return msgs;
- }
- void Translation::_set_messages(const DVector<String>& p_messages){
- int msg_count=p_messages.size();
- ERR_FAIL_COND(msg_count%2);
- DVector<String>::Read r = p_messages.read();
- for(int i=0;i<msg_count;i+=2) {
- add_message( r[i+0], r[i+1] );
- }
- }
- void Translation::set_locale(const String& p_locale) {
- ERR_EXPLAIN("Invalid Locale: "+p_locale);
- ERR_FAIL_COND(!is_valid_locale(p_locale));
- locale=p_locale;
- }
- void Translation::add_message( const StringName& p_src_text, const StringName& p_xlated_text ) {
- translation_map[p_src_text]=p_xlated_text;
- }
- StringName Translation::get_message(const StringName& p_src_text) const {
- const Map<StringName, StringName>::Element *E=translation_map.find(p_src_text);
- if (!E)
- return StringName();
- return E->get();
- }
- void Translation::erase_message(const StringName& p_src_text) {
- translation_map.erase(p_src_text);
- }
- void Translation::get_message_list(List<StringName> *r_messages) const {
- for (const Map<StringName, StringName>::Element *E=translation_map.front();E;E=E->next()) {
- r_messages->push_back(E->key());
- }
- }
- int Translation::get_message_count() const {
- return translation_map.size();
- };
- void Translation::_bind_methods() {
- ObjectTypeDB::bind_method(_MD("set_locale","locale"),&Translation::set_locale);
- ObjectTypeDB::bind_method(_MD("get_locale"),&Translation::get_locale);
- ObjectTypeDB::bind_method(_MD("add_message","src_message","xlated_message"),&Translation::add_message);
- ObjectTypeDB::bind_method(_MD("get_message","src_message"),&Translation::get_message);
- ObjectTypeDB::bind_method(_MD("erase_message","src_message"),&Translation::erase_message);
- ObjectTypeDB::bind_method(_MD("get_message_list"),&Translation::_get_message_list);
- ObjectTypeDB::bind_method(_MD("get_message_count"),&Translation::get_message_count);
- ObjectTypeDB::bind_method(_MD("_set_messages"),&Translation::_set_messages);
- ObjectTypeDB::bind_method(_MD("_get_messages"),&Translation::_get_messages);
- ADD_PROPERTY( PropertyInfo(Variant::STRING_ARRAY,"messages",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR), _SCS("_set_messages"), _SCS("_get_messages") );
- ADD_PROPERTY( PropertyInfo(Variant::STRING,"locale"), _SCS("set_locale"), _SCS("get_locale") );
- }
- Translation::Translation() {
- locale="en";
- }
- ///////////////////////////////////////////////
- void TranslationServer::set_locale(const String& p_locale) {
- ERR_EXPLAIN("Invalid Locale: "+p_locale);
- ERR_FAIL_COND(!is_valid_locale(p_locale));
- locale=p_locale;
- }
- String TranslationServer::get_locale() const {
- return locale;
- }
- void TranslationServer::add_translation(const Ref<Translation> &p_translation) {
- translations.insert(p_translation);
- }
- void TranslationServer::remove_translation(const Ref<Translation> &p_translation) {
- translations.erase(p_translation);
- }
- void TranslationServer::clear() {
- translations.clear();
- };
- StringName TranslationServer::translate(const StringName& p_message) const {
- //translate using locale
- if (!enabled)
- return p_message;
- StringName res;
- bool near_match=false;
- const CharType *lptr=&locale[0];
- for (const Set< Ref<Translation> >::Element *E=translations.front();E;E=E->next()) {
- const Ref<Translation>& t = E->get();
- String l = t->get_locale();
- if (lptr[0]!=l[0] || lptr[1]!=l[1])
- continue; // locale not match
- //near match
- bool match = (l!=locale);
- if (near_match && !match)
- continue; //only near-match once
- StringName r=t->get_message(p_message);
- if (!r)
- continue;
- res=r;
- if (match)
- break;
- else
- near_match=true;
- }
- if (!res) {
- //try again with fallback
- if (fallback.length()>=2) {
- const CharType *fptr=&fallback[0];
- bool near_match=false;
- for (const Set< Ref<Translation> >::Element *E=translations.front();E;E=E->next()) {
- const Ref<Translation>& t = E->get();
- String l = t->get_locale();
- if (fptr[0]!=l[0] || fptr[1]!=l[1])
- continue; // locale not match
- //near match
- bool match = (l!=fallback);
- if (near_match && !match)
- continue; //only near-match once
- StringName r=t->get_message(p_message);
- if (!r)
- continue;
- res=r;
- if (match)
- break;
- else
- near_match=true;
- }
- }
- }
- if (!res)
- return p_message;
- return res;
- }
- TranslationServer *TranslationServer::singleton=NULL;
- bool TranslationServer::_load_translations(const String& p_from) {
- if (Globals::get_singleton()->has(p_from)) {
- DVector<String> translations=Globals::get_singleton()->get(p_from);
- int tcount=translations.size();
- if (tcount) {
- DVector<String>::Read r = translations.read();
- for(int i=0;i<tcount;i++) {
- print_line( "Loading translation from " + r[i] );
- Ref<Translation> tr = ResourceLoader::load(r[i]);
- if (tr.is_valid())
- add_translation(tr);
- }
- }
- return true;
- }
- return false;
- }
- void TranslationServer::setup() {
- String test = GLOBAL_DEF("locale/test","");
- test=test.strip_edges();
- if (test!="")
- set_locale( test );
- else
- set_locale( OS::get_singleton()->get_locale() );
- fallback = GLOBAL_DEF("locale/fallback","en");
- #ifdef TOOLS_ENABLED
- {
- String options="";
- int idx=0;
- while(locale_list[idx]) {
- if (idx>0)
- options+=", ";
- options+=locale_list[idx];
- idx++;
- }
- Globals::get_singleton()->set_custom_property_info("locale/fallback",PropertyInfo(Variant::STRING,"locale/fallback",PROPERTY_HINT_ENUM,options));
- }
- #endif
- //load translations
- }
- void TranslationServer::_bind_methods() {
- ObjectTypeDB::bind_method(_MD("set_locale","locale"),&TranslationServer::set_locale);
- ObjectTypeDB::bind_method(_MD("get_locale"),&TranslationServer::get_locale);
- ObjectTypeDB::bind_method(_MD("translate"),&TranslationServer::translate);
- ObjectTypeDB::bind_method(_MD("add_translation"),&TranslationServer::add_translation);
- ObjectTypeDB::bind_method(_MD("remove_translation"),&TranslationServer::remove_translation);
- ObjectTypeDB::bind_method(_MD("clear"),&TranslationServer::clear);
- }
- void TranslationServer::load_translations() {
- String locale = get_locale();
- bool found = _load_translations("locale/translations"); //all
- if (_load_translations("locale/translations_"+locale.substr(0,2)))
- found=true;
- if ( locale.substr(0,2) != locale ) {
- if (_load_translations("locale/translations_"+locale))
- found=true;
- }
- }
- TranslationServer::TranslationServer() {
- singleton=this;
- locale="en";
- enabled=true;
- }
|