Added translation support to Godot
included is a French translation!
This commit is contained in:
parent
8be2fabbe5
commit
bccdc11dde
10 changed files with 5847 additions and 13 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -19,6 +19,7 @@ tools/editor/register_exporters.cpp
|
|||
tools/editor/doc_data_compressed.h
|
||||
tools/editor/certs_compressed.h
|
||||
tools/editor/editor_icons.cpp
|
||||
tools/editor/translations.h
|
||||
-fpic
|
||||
.fscache
|
||||
make.bat
|
||||
|
|
|
@ -135,7 +135,7 @@ size_t FileAccessMemory::get_len() const {
|
|||
|
||||
bool FileAccessMemory::eof_reached() const {
|
||||
|
||||
return pos >= length;
|
||||
return pos > length;
|
||||
}
|
||||
|
||||
uint8_t FileAccessMemory::get_8() const {
|
||||
|
|
|
@ -30,13 +30,8 @@
|
|||
#include "os/file_access.h"
|
||||
#include "translation.h"
|
||||
|
||||
RES TranslationLoaderPO::load(const String &p_path, const String& p_original_path, Error *r_error) {
|
||||
|
||||
if (r_error)
|
||||
*r_error=ERR_CANT_OPEN;
|
||||
|
||||
FileAccess *f=FileAccess::open(p_path,FileAccess::READ);
|
||||
ERR_FAIL_COND_V(!f,RES());
|
||||
RES TranslationLoaderPO::load_translation(FileAccess *f, Error *r_error, const String &p_path) {
|
||||
|
||||
String l = f->get_line();
|
||||
|
||||
|
@ -52,6 +47,8 @@ RES TranslationLoaderPO::load(const String &p_path, const String& p_original_pat
|
|||
String msg_id;
|
||||
String msg_str;
|
||||
String config;
|
||||
int msg_line=0;
|
||||
|
||||
if (r_error)
|
||||
*r_error=ERR_FILE_CORRUPT;
|
||||
|
||||
|
@ -87,7 +84,7 @@ RES TranslationLoaderPO::load(const String &p_path, const String& p_original_pat
|
|||
if (status==STATUS_READING_ID) {
|
||||
|
||||
memdelete(f);
|
||||
ERR_EXPLAIN(p_path+":"+itos(line)+" nexpected 'msgid', was expecting 'msgstr' while parsing: ");
|
||||
ERR_EXPLAIN(p_path+":"+itos(line)+" Unexpected 'msgid', was expecting 'msgstr' while parsing: ");
|
||||
ERR_FAIL_V(RES());
|
||||
}
|
||||
|
||||
|
@ -100,6 +97,7 @@ RES TranslationLoaderPO::load(const String &p_path, const String& p_original_pat
|
|||
status=STATUS_READING_ID;
|
||||
msg_id="";
|
||||
msg_str="";
|
||||
msg_line=line;
|
||||
}
|
||||
|
||||
if (l.begins_with("msgstr")) {
|
||||
|
@ -113,6 +111,7 @@ RES TranslationLoaderPO::load(const String &p_path, const String& p_original_pat
|
|||
|
||||
l=l.substr(6,l.length()).strip_edges();
|
||||
status=STATUS_READING_STRING;
|
||||
msg_line=line;
|
||||
}
|
||||
|
||||
if (l=="" || l.begins_with("#")) {
|
||||
|
@ -183,6 +182,18 @@ RES TranslationLoaderPO::load(const String &p_path, const String& p_original_pat
|
|||
*r_error=OK;
|
||||
|
||||
return translation;
|
||||
}
|
||||
|
||||
RES TranslationLoaderPO::load(const String &p_path, const String& p_original_path, Error *r_error) {
|
||||
|
||||
if (r_error)
|
||||
*r_error=ERR_CANT_OPEN;
|
||||
|
||||
FileAccess *f=FileAccess::open(p_path,FileAccess::READ);
|
||||
ERR_FAIL_COND_V(!f,RES());
|
||||
|
||||
|
||||
return load_translation(f,r_error);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -30,10 +30,12 @@
|
|||
#define TRANSLATION_LOADER_PO_H
|
||||
|
||||
#include "io/resource_loader.h"
|
||||
|
||||
#include "translation.h"
|
||||
#include "os/file_access.h"
|
||||
class TranslationLoaderPO : public ResourceFormatLoader {
|
||||
public:
|
||||
|
||||
static RES load_translation(FileAccess *f, Error *r_error,const String& p_path=String());
|
||||
virtual RES load(const String &p_path,const String& p_original_path="",Error *r_error=NULL);
|
||||
virtual void get_recognized_extensions(List<String> *p_extensions) const;
|
||||
virtual bool handles_type(const String& p_type) const;
|
||||
|
|
|
@ -85,6 +85,7 @@ enum PropertyUsageFlags {
|
|||
PROPERTY_USAGE_STORE_IF_NONZERO=512, //only store if nonzero
|
||||
PROPERTY_USAGE_STORE_IF_NONONE=1024, //only store if false
|
||||
PROPERTY_USAGE_NO_INSTANCE_STATE=2048,
|
||||
PROPERTY_USAGE_RESTART_IF_CHANGED=4096,
|
||||
|
||||
PROPERTY_USAGE_DEFAULT=PROPERTY_USAGE_STORAGE|PROPERTY_USAGE_EDITOR|PROPERTY_USAGE_NETWORK,
|
||||
PROPERTY_USAGE_DEFAULT_INTL=PROPERTY_USAGE_STORAGE|PROPERTY_USAGE_EDITOR|PROPERTY_USAGE_NETWORK|PROPERTY_USAGE_INTERNATIONALIZED,
|
||||
|
|
|
@ -672,10 +672,12 @@ void TranslationServer::set_tool_translation(const Ref<Translation>& p_translati
|
|||
StringName TranslationServer::tool_translate(const StringName& p_message) const {
|
||||
|
||||
if (tool_translation.is_valid()) {
|
||||
StringName r = tool_translation->tr(p_message);
|
||||
if (r)
|
||||
StringName r = tool_translation->get_message(p_message);
|
||||
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
return p_message;
|
||||
}
|
||||
|
|
64
tools/SCsub
64
tools/SCsub
|
@ -5,7 +5,71 @@ env.add_source_files(env.tool_sources,"*.cpp")
|
|||
|
||||
Export('env')
|
||||
|
||||
|
||||
def make_translations_header(target,source,env):
|
||||
|
||||
|
||||
dst = target[0].srcnode().abspath
|
||||
|
||||
g = open(dst,"wb")
|
||||
|
||||
|
||||
""""
|
||||
"""
|
||||
|
||||
g.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n")
|
||||
g.write("#ifndef _EDITOR_TRANSLATIONS_H\n")
|
||||
g.write("#define _EDITOR_TRANSLATIONS_H\n")
|
||||
|
||||
xl_names=[]
|
||||
for i in range(len(source)):
|
||||
print("Appending translation: "+source[i].srcnode().abspath)
|
||||
f = open(source[i].srcnode().abspath,"rb")
|
||||
buf = f.read()
|
||||
decomp_size = len(buf)
|
||||
import zlib
|
||||
import os.path
|
||||
buf = zlib.compress(buf)
|
||||
|
||||
name = os.path.splitext(os.path.basename(source[i].srcnode().abspath))[0]
|
||||
|
||||
#g.write("static const int _translation_"+name+"_compressed_size="+str(len(buf))+";\n")
|
||||
#g.write("static const int _translation_"+name+"_uncompressed_size="+str(decomp_size)+";\n")
|
||||
g.write("static const unsigned char _translation_"+name+"_compressed[]={\n")
|
||||
for i in range(len(buf)):
|
||||
g.write(str(ord(buf[i]))+",\n")
|
||||
|
||||
g.write("};\n")
|
||||
|
||||
xl_names.append([name,len(buf),str(decomp_size)])
|
||||
|
||||
g.write("struct EditorTranslationList {\n")
|
||||
g.write("\tconst char* lang;\n");
|
||||
g.write("\tint comp_size;\n");
|
||||
g.write("\tint uncomp_size;\n");
|
||||
g.write("\tconst unsigned char* data;\n");
|
||||
g.write("};\n\n");
|
||||
g.write("static EditorTranslationList _editor_translations[]={\n")
|
||||
for x in xl_names:
|
||||
g.write("\t{ \""+x[0]+"\", "+str(x[1])+", "+str(x[2])+",_translation_"+x[0]+"_compressed},\n")
|
||||
g.write("\t{NULL,0,0,NULL}\n")
|
||||
g.write("};\n")
|
||||
|
||||
g.write("#endif")
|
||||
|
||||
|
||||
|
||||
if (env["tools"]!="no"):
|
||||
|
||||
import glob
|
||||
|
||||
dir = env.Dir('.').abspath
|
||||
tlist = glob.glob(dir + "/translations/*.po")
|
||||
|
||||
print("translations: ",tlist)
|
||||
env.Depends('#tools/editor/translations.h',tlist)
|
||||
env.Command('#tools/editor/translations.h',tlist,make_translations_header)
|
||||
|
||||
SConscript('editor/SCsub');
|
||||
#SConscript('scintilla/SCsub');
|
||||
SConscript('collada/SCsub');
|
||||
|
|
|
@ -41,6 +41,10 @@
|
|||
#include "io/config_file.h"
|
||||
#include "editor_node.h"
|
||||
#include "globals.h"
|
||||
#include "translations.h"
|
||||
#include "io/file_access_memory.h"
|
||||
#include "io/translation_loader_po.h"
|
||||
#include "io/compression.h"
|
||||
|
||||
Ref<EditorSettings> EditorSettings::singleton=NULL;
|
||||
|
||||
|
@ -284,6 +288,7 @@ void EditorSettings::create() {
|
|||
print_line("EditorSettings: Load OK!");
|
||||
}
|
||||
|
||||
singleton->setup_language();
|
||||
singleton->setup_network();
|
||||
singleton->load_favorites();
|
||||
singleton->list_text_editor_themes();
|
||||
|
@ -310,9 +315,11 @@ void EditorSettings::create() {
|
|||
singleton->config_file_path=config_file_path;
|
||||
singleton->settings_path=config_path+"/"+config_dir;
|
||||
singleton->_load_defaults(extra_config);
|
||||
singleton->setup_language();
|
||||
singleton->setup_network();
|
||||
singleton->list_text_editor_themes();
|
||||
|
||||
|
||||
}
|
||||
|
||||
String EditorSettings::get_settings_path() const {
|
||||
|
@ -322,6 +329,23 @@ String EditorSettings::get_settings_path() const {
|
|||
|
||||
|
||||
|
||||
void EditorSettings::setup_language() {
|
||||
|
||||
String lang = get("global/editor_language");
|
||||
print_line("LANG IS "+lang);
|
||||
if (lang=="en")
|
||||
return; //none to do
|
||||
|
||||
for(int i=0;i<translations.size();i++) {
|
||||
print_line("TESTING "+translations[i]->get_locale());
|
||||
if (translations[i]->get_locale()==lang) {
|
||||
print_line("ok translation");
|
||||
TranslationServer::get_singleton()->set_tool_translation(translations[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EditorSettings::setup_network() {
|
||||
|
||||
List<IP_Address> local_ip;
|
||||
|
@ -389,6 +413,36 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
|
|||
|
||||
_THREAD_SAFE_METHOD_
|
||||
|
||||
|
||||
{
|
||||
String lang_hint="en";
|
||||
String host_lang = OS::get_singleton()->get_locale();
|
||||
|
||||
String best;
|
||||
|
||||
for(int i=0;i<translations.size();i++) {
|
||||
String locale = translations[i]->get_locale();
|
||||
lang_hint+=",";
|
||||
lang_hint+=locale;
|
||||
|
||||
if (host_lang==locale) {
|
||||
best=locale;
|
||||
}
|
||||
|
||||
if (best==String() && host_lang.begins_with(locale)) {
|
||||
best=locale;
|
||||
}
|
||||
}
|
||||
|
||||
if (best==String()) {
|
||||
best="en";
|
||||
}
|
||||
|
||||
set("global/editor_language",best);
|
||||
hints["global/editor_language"]=PropertyInfo(Variant::STRING,"global/editor_language",PROPERTY_HINT_ENUM,lang_hint,PROPERTY_USAGE_DEFAULT|PROPERTY_USAGE_RESTART_IF_CHANGED);
|
||||
}
|
||||
|
||||
set("global/show_script_in_scene_tabs",false);
|
||||
set("global/font","");
|
||||
hints["global/font"]=PropertyInfo(Variant::STRING,"global/font",PROPERTY_HINT_GLOBAL_FILE,"*.fnt");
|
||||
set("global/autoscan_project_path","");
|
||||
|
@ -399,6 +453,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
|
|||
hints["global/default_project_export_path"]=PropertyInfo(Variant::STRING,"global/default_project_export_path",PROPERTY_HINT_GLOBAL_DIR);
|
||||
set("global/show_script_in_scene_tabs",false);
|
||||
|
||||
|
||||
set("text_editor/color_theme","Default");
|
||||
hints["text_editor/color_theme"]=PropertyInfo(Variant::STRING,"text_editor/color_theme",PROPERTY_HINT_ENUM,"Default");
|
||||
|
||||
|
@ -821,7 +876,32 @@ EditorSettings::EditorSettings() {
|
|||
|
||||
//singleton=this;
|
||||
last_order=0;
|
||||
|
||||
EditorTranslationList *etl=_editor_translations;
|
||||
|
||||
while(etl->data) {
|
||||
|
||||
Vector<uint8_t> data;
|
||||
data.resize(etl->uncomp_size);
|
||||
Compression::decompress(data.ptr(),etl->uncomp_size,etl->data,etl->comp_size,Compression::MODE_DEFLATE);
|
||||
|
||||
FileAccessMemory *fa = memnew (FileAccessMemory);
|
||||
fa->open_custom(data.ptr(),data.size());
|
||||
|
||||
Ref<Translation> tr = TranslationLoaderPO::load_translation(fa,NULL,"translation_"+String(etl->lang));
|
||||
|
||||
if (tr.is_valid()) {
|
||||
tr->set_locale(etl->lang);
|
||||
translations.push_back(tr);
|
||||
}
|
||||
|
||||
etl++;
|
||||
|
||||
}
|
||||
|
||||
_load_defaults();
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
#include "resource.h"
|
||||
#include "os/thread_safe.h"
|
||||
#include "core/io/config_file.h"
|
||||
|
||||
#include "translation.h"
|
||||
class EditorPlugin;
|
||||
|
||||
class EditorSettings : public Resource {
|
||||
|
@ -93,6 +93,8 @@ private:
|
|||
Vector<String> favorite_dirs;
|
||||
Vector<String> recent_dirs;
|
||||
|
||||
Vector<Ref<Translation> > translations;
|
||||
|
||||
protected:
|
||||
|
||||
static void _bind_methods();
|
||||
|
@ -111,6 +113,7 @@ public:
|
|||
String get_project_settings_path() const;
|
||||
|
||||
|
||||
void setup_language();
|
||||
void setup_network();
|
||||
|
||||
void raise_order(const String& p_name);
|
||||
|
|
5670
tools/translations/fr.po
Normal file
5670
tools/translations/fr.po
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue