summaryrefslogtreecommitdiffstats
path: root/core/translation.cpp
diff options
context:
space:
mode:
authorJuan Linietsky <reduzio@gmail.com>2014-02-09 22:10:30 -0300
committerJuan Linietsky <reduzio@gmail.com>2014-02-09 22:10:30 -0300
commit0b806ee0fc9097fa7bda7ac0109191c9c5e0a1ac (patch)
tree276c4d099e178eb67fbd14f61d77b05e3808e9e3 /core/translation.cpp
parent0e49da1687bc8192ed210947da52c9e5c5f301bb (diff)
downloadredot-engine-0b806ee0fc9097fa7bda7ac0109191c9c5e0a1ac.tar.gz
GODOT IS OPEN SOURCE
Diffstat (limited to 'core/translation.cpp')
-rw-r--r--core/translation.cpp646
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;
+
+}