diff options
author | Juan Linietsky <reduzio@gmail.com> | 2014-02-09 22:10:30 -0300 |
---|---|---|
committer | Juan Linietsky <reduzio@gmail.com> | 2014-02-09 22:10:30 -0300 |
commit | 0b806ee0fc9097fa7bda7ac0109191c9c5e0a1ac (patch) | |
tree | 276c4d099e178eb67fbd14f61d77b05e3808e9e3 /core/translation.cpp | |
parent | 0e49da1687bc8192ed210947da52c9e5c5f301bb (diff) | |
download | redot-engine-0b806ee0fc9097fa7bda7ac0109191c9c5e0a1ac.tar.gz |
GODOT IS OPEN SOURCE
Diffstat (limited to 'core/translation.cpp')
-rw-r--r-- | core/translation.cpp | 646 |
1 files changed, 646 insertions, 0 deletions
diff --git a/core/translation.cpp b/core/translation.cpp new file mode 100644 index 0000000000..045771f7c7 --- /dev/null +++ b/core/translation.cpp @@ -0,0 +1,646 @@ +/*************************************************************************/ +/* translation.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2014 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()); + } + +} + + +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("_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); +} + +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!=lptr); + + 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() { + + + set_locale( GLOBAL_DEF("locale/default",OS::get_singleton()->get_locale()) ); + fallback = GLOBAL_DEF("locale/fallback",""); + //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); +} + +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; + } + + + if (!found && fallback!="") { //none found anywhere, use fallback + + _load_translations("locale/translations_"+fallback.substr(0,2)); + if ( fallback.substr(0,2) != fallback ) { + _load_translations("locale/translations_"+fallback); + } + + this->locale=fallback; + + } + +} + +TranslationServer::TranslationServer() { + + + singleton=this; + locale="en"; + enabled=true; + +} |