diff options
author | Andrew Tridgell <tridge@samba.org> | 2003-08-13 01:53:07 +0000 |
---|---|---|
committer | Andrew Tridgell <tridge@samba.org> | 2003-08-13 01:53:07 +0000 |
commit | ef2e26c91b80556af033d3335e55f5dfa6fff31d (patch) | |
tree | faa21bfd7e7b5247250b47c7891dc1a5ebee6be9 /source4/intl | |
download | samba-ef2e26c91b80556af033d3335e55f5dfa6fff31d.tar.gz samba-ef2e26c91b80556af033d3335e55f5dfa6fff31d.tar.xz samba-ef2e26c91b80556af033d3335e55f5dfa6fff31d.zip |
first public release of samba4 code
(This used to be commit b0510b5428b3461aeb9bbe3cc95f62fc73e2b97f)
Diffstat (limited to 'source4/intl')
-rw-r--r-- | source4/intl/.cvsignore | 2 | ||||
-rw-r--r-- | source4/intl/lang_tdb.c | 235 | ||||
-rw-r--r-- | source4/intl/linux-msg.sed | 100 |
3 files changed, 337 insertions, 0 deletions
diff --git a/source4/intl/.cvsignore b/source4/intl/.cvsignore new file mode 100644 index 00000000000..5f2a5c4cf75 --- /dev/null +++ b/source4/intl/.cvsignore @@ -0,0 +1,2 @@ +*.po +*.po32 diff --git a/source4/intl/lang_tdb.c b/source4/intl/lang_tdb.c new file mode 100644 index 00000000000..6879d70d166 --- /dev/null +++ b/source4/intl/lang_tdb.c @@ -0,0 +1,235 @@ +/* + Unix SMB/CIFS implementation. + tdb based replacement for gettext + Copyright (C) Andrew Tridgell 2001 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +static TDB_CONTEXT *tdb; + +/* the currently selected language */ +static char *current_lang; + + +/* load a msg file into the tdb */ +static BOOL load_msg(const char *msg_file) +{ + char **lines; + int num_lines, i; + char *msgid, *msgstr; + TDB_DATA key, data; + + lines = file_lines_load(msg_file, &num_lines); + + if (!lines) { + return False; + } + + if (tdb_lockall(tdb) != 0) return False; + + /* wipe the db */ + tdb_traverse(tdb, tdb_traverse_delete_fn, NULL); + + msgid = NULL; + + for (i=0;i<num_lines;i++) { + if (strncmp(lines[i], "msgid \"", 7) == 0) { + msgid = lines[i] + 7; + } + if (msgid && strncmp(lines[i], "msgstr \"", 8) == 0) { + msgstr = lines[i] + 8; + trim_string(msgid, NULL, "\""); + trim_string(msgstr, NULL, "\""); + if (*msgstr == 0) { + msgstr = msgid; + } + key.dptr = msgid; + key.dsize = strlen(msgid)+1; + data.dptr = msgstr; + data.dsize = strlen(msgstr)+1; + tdb_store(tdb, key, data, 0); + msgid = NULL; + } + } + + file_lines_free(lines); + tdb_unlockall(tdb); + + return True; +} + + +/* work out what language to use from locale variables */ +static const char *get_lang(void) +{ + const char *vars[] = {"LANGUAGE", "LC_ALL", "LC_LANG", "LANG", NULL}; + int i; + char *p; + + for (i=0; vars[i]; i++) { + if ((p = getenv(vars[i]))) { + return p; + } + } + + return NULL; +} + +/* initialise the message translation subsystem. If the "lang" argument + is NULL then get the language from the normal environment variables */ +BOOL lang_tdb_init(const char *lang) +{ + char *path = NULL; + char *msg_path = NULL; + struct stat st; + static int initialised; + time_t loadtime; + TALLOC_CTX *mem_ctx; + + /* we only want to init once per process, unless given + an override */ + if (initialised && !lang) return True; + + if (initialised) { + /* we are re-initialising, free up any old init */ + if (tdb) { + tdb_close(tdb); + tdb = NULL; + } + SAFE_FREE(current_lang); + } + + initialised = 1; + + if (!lang) { + /* no lang given, use environment */ + lang = get_lang(); + } + + /* if no lang then we don't translate */ + if (!lang) return True; + + mem_ctx = talloc_init("lang_tdb_init"); + if (!mem_ctx) { + return False; + } + asprintf(&msg_path, "%s.msg", lib_path(mem_ctx, (const char *)lang)); + if (stat(msg_path, &st) != 0) { + /* the msg file isn't available */ + free(msg_path); + talloc_destroy(mem_ctx); + return False; + } + + + asprintf(&path, "%s%s.tdb", lock_path(mem_ctx, "lang_"), lang); + + tdb = tdb_open_log(path, 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0644); + if (!tdb) { + tdb = tdb_open_log(path, 0, TDB_DEFAULT, O_RDONLY, 0); + free(path); + free(msg_path); + talloc_destroy(mem_ctx); + if (!tdb) return False; + current_lang = strdup(lang); + return True; + } + + free(path); + talloc_destroy(mem_ctx); + + loadtime = tdb_fetch_int32(tdb, "/LOADTIME/"); + + if (loadtime == -1 || loadtime < st.st_mtime) { + load_msg(msg_path); + tdb_store_int32(tdb, "/LOADTIME/", (int)time(NULL)); + } + free(msg_path); + + current_lang = strdup(lang); + + return True; +} + +/* translate a msgid to a message string in the current language + returns a string that must be freed by calling lang_msg_free() +*/ +const char *lang_msg(const char *msgid) +{ + TDB_DATA key, data; + + lang_tdb_init(NULL); + + if (!tdb) return msgid; + + key.dptr = strdup(msgid); + key.dsize = strlen(msgid)+1; + + data = tdb_fetch(tdb, key); + + free(key.dptr); + + /* if the message isn't found then we still need to return a pointer + that can be freed. Pity. */ + if (!data.dptr) + return strdup(msgid); + + return (const char *)data.dptr; +} + + +/* free up a string from lang_msg() */ +void lang_msg_free(const char *msgstr) +{ + if (!tdb) return; + free(msgstr); +} + + +/* + when the _() translation macro is used there is no obvious place to free + the resulting string and there is no easy way to give a static pointer. + All we can do is rotate between some static buffers and hope a single d_printf() + doesn't have more calls to _() than the number of buffers +*/ +const char *lang_msg_rotate(const char *msgid) +{ +#define NUM_LANG_BUFS 4 + const char *msgstr; + static pstring bufs[NUM_LANG_BUFS]; + static int next; + + msgstr = lang_msg(msgid); + if (!msgstr) return msgid; + + pstrcpy(bufs[next], msgstr); + msgstr = bufs[next]; + + next = (next+1) % NUM_LANG_BUFS; + + return msgstr; +} + + +/* + return the current language - needed for language file mappings +*/ +char *lang_tdb_current(void) +{ + return current_lang; +} diff --git a/source4/intl/linux-msg.sed b/source4/intl/linux-msg.sed new file mode 100644 index 00000000000..5918e720a9a --- /dev/null +++ b/source4/intl/linux-msg.sed @@ -0,0 +1,100 @@ +# po2msg.sed - Convert Uniforum style .po file to Linux style .msg file +# Copyright (C) 1995 Free Software Foundation, Inc. +# Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# +# The first directive in the .msg should be the definition of the +# message set number. We use always set number 1. +# +1 { + i\ +$set 1 # Automatically created by po2msg.sed + h + s/.*/0/ + x +} +# +# Mitch's old catalog format does not allow comments. +# +# We copy the original message as a comment into the .msg file. +# +/^msgid/ { + s/msgid[ ]*"// +# +# This does not work now with the new format. +# /"$/! { +# s/\\$// +# s/$/ ... (more lines following)"/ +# } + x +# The following nice solution is by +# Bruno <Haible@ma2s2.mathematik.uni-karlsruhe.de> + td +# Increment a decimal number in pattern space. +# First hide trailing `9' digits. + :d + s/9\(_*\)$/_\1/ + td +# Assure at least one digit is available. + s/^\(_*\)$/0\1/ +# Increment the last digit. + s/8\(_*\)$/9\1/ + s/7\(_*\)$/8\1/ + s/6\(_*\)$/7\1/ + s/5\(_*\)$/6\1/ + s/4\(_*\)$/5\1/ + s/3\(_*\)$/4\1/ + s/2\(_*\)$/3\1/ + s/1\(_*\)$/2\1/ + s/0\(_*\)$/1\1/ +# Convert the hidden `9' digits to `0's. + s/_/0/g + x + G + s/\(.*\)"\n\([0-9]*\)/$ #\2 Original Message:(\1)/p +} +# +# The .msg file contains, other then the .po file, only the translations +# but each given a unique ID. Starting from 1 and incrementing by 1 for +# each message we assign them to the messages. +# It is important that the .po file used to generate the cat-id-tbl.c file +# (with po-to-tbl) is the same as the one used here. (At least the order +# of declarations must not be changed.) +# +/^msgstr/ { + s/msgstr[ ]*"\(.*\)"/# \1/ +# Clear substitution flag. + tb +# Append the next line. + :b + N +# Look whether second part is continuation line. + s/\(.*\n\)"\(.*\)"/\1\2/ +# Yes, then branch. + ta + P + D +# Note that D includes a jump to the start!! +# We found a continuation line. But before printing insert '\'. + :a + s/\(.*\)\(\n.*\)/\1\\\2/ + P +# We cannot use D here. + s/.*\n\(.*\)/\1/ + tb +} +d |