From 248be6ffcdbc6de89208e685361c7437c27f4f03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20T=C3=A4nzer?= Date: Tue, 27 Sep 2011 23:53:15 +0200 Subject: bug 985: Remove special non-ASCII character from msgid MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Michael Tänzer --- CommModule/client.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CommModule/client.pl b/CommModule/client.pl index 323ee27..44be6f2 100755 --- a/CommModule/client.pl +++ b/CommModule/client.pl @@ -887,7 +887,7 @@ sub HandleCerts($$) my $body = _("Hi")." $user{fname},\n\n"; $body .= sprintf(_("You can collect your certificate for %s by going to the following location:")."\n\n", $row{'email'}.$row{'CN'}); $body .= "https://www.cacert.org/account.php?id=".($server?"15":"6")."&cert=$row{id}\n\n"; - $body .= _("If you have not imported CAcert´s root certificate, please go to:")."\n"; + $body .= _("If you have not imported CAcert's root certificate, please go to:")."\n"; $body .= "https://www.cacert.org/index.php?id=3\n"; $body .= "Root cert fingerprint = A6:1B:37:5E:39:0D:9C:36:54:EE:BD:20:31:46:1F:6B\n"; $body .= "Root cert fingerprint = 135C EC36 F49C B8E9 3B1A B270 CD80 8846 76CE 8F33\n\n"; -- cgit v1.2.1 From c99e1025667d8fef72b6fdbe7d34769a279a8942 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20T=C3=A4nzer?= Date: Wed, 28 Sep 2011 00:00:25 +0200 Subject: bug 985: add all possible locales and use new directory layout MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Michael Tänzer --- locale/make.php | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/locale/make.php b/locale/make.php index 859d75e..2ffd5a0 100755 --- a/locale/make.php +++ b/locale/make.php @@ -2,11 +2,13 @@ "bg_BG", "da" => "da_DK", "de" => "de_DE", "es" => "es_ES", "fr" => "fr_FR", "fi" => "fi_FI", "he" => "he_IL", "hr" => "hr_HR", - "hu" => "hu_HU", "it" => "it_IT", "ja" => "ja_JP", "nl" => "nl_NL", - "pt" => "pt_PT", "ro" => "ro_RO", "ru" => "ru_RU", "fa" => "fa_IR", - "sv" => "sv_SE", "tr" => "tr_TR", "zh" => "zh_CN", "ar" => "ar_SY", + "hu" => "hu_HU", "id" => "id_ID", "it" => "it_IT", "ja" => "ja_JP", + "nl" => "nl_NL", "lv" => "lv_LV", "pt" => "pt_PT", "pt_BR" => "pt_BR", + "ro" => "ro_RO", "ru" => "ru_RU", "fa" => "fa_IR", "sv" => "sv_SE", + "tr" => "tr_TR", "zh_CN" => "zh_CN", "zh_TW" => "zh_TW", "ar" => "ar_SY", "el" => "el_GR", "tl" => "tl_PH", "pl" => "pl_PL", "cs" => "cs_CZ", - "ka" => "ka_GE", "is" => "is_IS", "ko" => "ko_KR", "nb" => "nb_NO"); + "ka" => "ka_GE", "is" => "is_IS", "ko" => "ko_KR", "nb" => "nb_NO", + "sl" => "sl_SI", "th" => "th_TH", "uk" => "uk_UA"); if($argc > 1) { @@ -14,21 +16,21 @@ { $val = $lang[$key]; if($val != "") - { - $do = `wget -O $key.po "http://translingo.cacert.org/export2.php?pid=1&editlanguage=$val" 2>&1`; -echo $do; + { echo `mkdir -p $key/LC_MESSAGES/`; - $do = `msgfmt -o $key/LC_MESSAGES/messages.mo $key.po 2>&1`; + $do = `wget -O $key/messages.po "http://translingo.cacert.org/export2.php?pid=1&editlanguage=$val" 2>&1`; +echo $do; + $do = `msgfmt -o $key/LC_MESSAGES/messages.mo $key/messages.po 2>&1`; echo $do; } } } else { foreach($lang as $key => $val) { - $do = `wget -O $key.po "http://translingo.cacert.org/export2.php?pid=1&editlanguage=$val" 2>&1`; -echo $do; echo `mkdir -p $key/LC_MESSAGES/`; - $do = `msgfmt -o $key/LC_MESSAGES/messages.mo $key.po 2>&1`; + $do = `wget -O $key/messages.po "http://translingo.cacert.org/export2.php?pid=1&editlanguage=$val" 2>&1`; +echo $do; + $do = `msgfmt -o $key/LC_MESSAGES/messages.mo $key/messages.po 2>&1`; echo $do; } } -- cgit v1.2.1 From dde0e7bd634e8a1130074e4e14b40222a65bc501 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20T=C3=A4nzer?= Date: Wed, 28 Sep 2011 00:11:54 +0200 Subject: bug 985: move from Translingo to Pootle (translations.cacert.org) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - new Makefile - rework translation selection code - remove unused files Signed-off-by: Michael Tänzer --- Makefile | 7 -- cacertupload.pl | 59 ----------------- includes/general.php | 166 ++++++++++++++++++++++++---------------------- locale/.gitignore | 3 +- locale/Makefile | 184 +++++++++++++++++++++++++++++++++++++++++++++++++++ locale/make.php | 37 ----------- password.dat.sample | 2 - 7 files changed, 274 insertions(+), 184 deletions(-) delete mode 100644 Makefile delete mode 100755 cacertupload.pl create mode 100644 locale/Makefile delete mode 100755 locale/make.php delete mode 100644 password.dat.sample diff --git a/Makefile b/Makefile deleted file mode 100644 index 914d979..0000000 --- a/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -all: - xgettext -s -o messages.po --no-wrap --foreign-user includes/*.php www/*.php pages/account/*.php pages/index/*.php pages/wot/*.php pages/gpg/*.php pages/disputes/*.php pages/help/*.php pages/disputes/*.php scripts/removedead.php - perl cacertupload.pl - cd locale; php make.php - -other: all - cat messages.po|sed "s/CHARSET/iso-8859-1/"|sed "s/PACKAGE VERSION/CAcert/"|sed "s/This file is put in the public domain./This file is distributed under the same license as the CAcert package./"|sed "s/# SOME DESCRIPTIVE TITLE.//" > messages.po diff --git a/cacertupload.pl b/cacertupload.pl deleted file mode 100755 index 991570b..0000000 --- a/cacertupload.pl +++ /dev/null @@ -1,59 +0,0 @@ -#!/usr/bin/perl - -#LibreSSL - CAcert web application -#Copyright (C) 2004-2008 CAcert Inc. -# -#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; version 2 of the License. -# -#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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -use LWP::UserAgent; -$ua = LWP::UserAgent->new(agent => 'Translingo Client 1.0'); -use HTTP::Request::Common qw(POST); - -my $translingo_password; -my $translingo_account; - -# Read Account&Password from file -eval `cat password.dat`; - -$ua->cookie_jar({}); -$ua->timeout(10000); - -my $req = POST 'http://translingo.cacert.org/login.php', -[ -]; -# ggf. Referer faken -$req->referer('http://translingo.cacert.org/'); - $ua->request($req)->as_string; - -# 1.Test - Umgebung -my $req = POST 'http://translingo.cacert.org/login.php', -[ - username => $translingo_account, - password => $translingo_password, - submit => 'Login', -]; -# ggf. Referer faken -$req->referer('http://translingo.cacert.org/'); -$ua->request($req)->as_string; - -# 2.Test - FileUpload -my $req = POST 'http://translingo.cacert.org/upload.php', -Content_Type => 'form-data', -Content => [ - project => '1', - fileformat => '1', - pofile => ["messages.po" => "messages.po", 'Content_Type' => "application/x-gettext"], -]; -print $ua->request($req)->as_string; - diff --git a/includes/general.php b/includes/general.php index ebdf20e..0231b21 100644 --- a/includes/general.php +++ b/includes/general.php @@ -70,50 +70,44 @@ } } - $lang = ""; - if(array_key_exists("lang",$_REQUEST)) - $lang=mysql_escape_string(substr(trim($_REQUEST['lang']), 0, 5)); - if($lang != "") - $_SESSION['_config']['language'] = $lang; - - //if($_SESSION['profile']['id'] == 1 && 1 == 2) - // echo $_SESSION['_config']['language']; - + + /////////////////////// + // Language Handling // + /////////////////////// + $_SESSION['_config']['translations'] = array( - "ar_JO" => "العربية", - "bg_BG" => "Български", - "cs_CZ" => "Čeština", - "da_DK" => "Dansk", - "de_DE" => "Deutsch", - "el_GR" => "Ελληνικά", - "en_AU" => "English", - "eo_EO" => "Esperanto", - "es_ES" => "Español", - "fa_IR" => "Farsi", - "fi_FI" => "Suomi", - "fr_FR" => "Français", - "he_IL" => "עברית", - "hr_HR" => "Hrvatski", - "hu_HU" => "Magyar", - "is_IS" => "Íslenska", - "it_IT" => "Italiano", - "ja_JP" => "日本語", - "ka_GE" => "Georgian", - "nl_NL" => "Nederlands", - "pl_PL" => "Polski", - "pt_PT" => "Português", - "pt_BR" => "Português Brasileiro", - "ru_RU" => "Русский", - "ro_RO" => "Română", - "sv_SE" => "Svenska", - "tr_TR" => "Türkçe", - "zh_CN" => "中文(简体)"); - - $value=array(); + "ar" => "العربية", + "bg" => "Български", + "cs" => "Čeština", + "da" => "Dansk", + "de" => "Deutsch", + "el" => "Ελληνικά", + "en" => "English", + "es" => "Español", + "fi" => "Suomi", + "fr" => "Français", + "hu" => "Magyar", + "it" => "Italiano", + "ja" => "日本語", + "lv" => "Latviešu", + "nl" => "Nederlands", + "pl" => "Polski", + "pt" => "Português", + "pt-br" => "Português Brasileiro", + "ru" => "Русский", + "sv" => "Svenska", + "tr" => "Türkçe", + "zh-cn" => "中文(简体)", + "zh-tw" => "中文(臺灣)"); + + if(!(array_key_exists('language',$_SESSION['_config']) && $_SESSION['_config']['language'] != "")) { - $bits = explode(",", strtolower(str_replace(" ", "", mysql_real_escape_string(array_key_exists('HTTP_ACCEPT_LANGUAGE',$_SERVER)?$_SERVER['HTTP_ACCEPT_LANGUAGE']:"")))); + $languages=array(); + + // parse Accept-Language header + $bits = explode(",", strtolower(str_replace(" ", "", array_key_exists('HTTP_ACCEPT_LANGUAGE',$_SERVER)?$_SERVER['HTTP_ACCEPT_LANGUAGE']:""))); foreach($bits as $lang) { $b = explode(";", $lang); @@ -121,59 +115,79 @@ $c = floatval(substr($b[1], 2)); else $c = 1; - $value["$c"] = trim($b[0]); + + if ($c != 0) + { + $languages["$c"] = trim($b[0]); + } } + + // check if there is an explicit language given as parameter + if(array_key_exists("lang",$_REQUEST) && trim($_REQUEST["lang"]) != "") + { + // higher priority as those values in the header + $languages["2.0"] = strtolower(trim($_REQUEST["lang"])); + } + + // fallback, qvalues may only have three digits after the . + $languages["0.0005"] = "en"; + + // remove any non-conforming values (that's why we don't need to + // mysql_real_escape() or escapeshellarg() but take care of the *) + // spec: ( ( 1*8ALPHA *( "-" 1*8ALPHA ) ) | "*" ) + $languages = preg_filter('/^(?:[a-zA-Z]{1,8}(?:-[a-zA-Z]{1,8})*|\*)$/', + '$0', $languages); - krsort($value); - - reset($value); + krsort($languages, SORT_NUMERIC); - foreach($value as $key => $val) + $all_translations = scandir($_SESSION['_config']['filepath']."/locale/"); + foreach($languages as $qvalue => $lang) { - $val = substr(escapeshellarg($val), 1, -1); - $short = substr($val, 0, 2); - if($val == "en" || $short == "en") + $lang = strtr($lang, '-', '_'); + $lang_length = strlen($lang); + $chosen_translation = ""; + foreach ($all_translations as $translation) { - $_SESSION['_config']['language'] = "en"; - break; - } - if(file_exists($_SESSION['_config']['filepath']."/locale/$val/LC_MESSAGES/messages.mo")) - { - $_SESSION['_config']['language'] = $val; - break; + $translation_lower = strtolower($translation); + if ($translation_lower === $lang || + substr($translation, 0, $lang_length + 1) === $lang.'_') + { + $chosen_translation = $translation; + break; + } } - if(file_exists($_SESSION['_config']['filepath']."/locale/$short/LC_MESSAGES/messages.mo")) + if ($chosen_translation !== "") { - $_SESSION['_config']['language'] = $short; - break; + if(file_exists($_SESSION['_config']['filepath']."/locale/$chosen_translation/LC_MESSAGES/messages.mo")) + { + $_SESSION['_config']['language'] = $lang; + break; + } } } } - if(!array_key_exists('_config',$_SESSION) || !array_key_exists('language',$_SESSION['_config']) || strlen($_SESSION['_config']['language']) != 5) + if(!array_key_exists('_config',$_SESSION) || + !array_key_exists('language',$_SESSION['_config']) || + $_SESSION['_config']['language'] == "" ) { - $lang = array_key_exists('language',$_SESSION['_config'])?$_SESSION['_config']['language']:""; - $_SESSION['_config']['language'] = "en_AU"; - foreach($_SESSION['_config']['translations'] as $key => $val) - { - if(substr($lang, 0, 2) == substr($key, 0, 2)) - { - $_SESSION['_config']['language'] = $val; - break; - } - } + $_SESSION['_config']['language'] = "en"; + trigger_error('$_SESSION[\'_config\'][\'language\'] was not set after '. + 'the translation search', E_USER_WARNING); } $_SESSION['_config']['recode'] = "html..latin-1"; - if($_SESSION['_config']['language'] == "zh_CN") + if($_SESSION['_config']['language'] === "zh_CN" || + $_SESSION['_config']['language'] === "zh_TW") { $_SESSION['_config']['recode'] = "html..gb2312"; - } else if($_SESSION['_config']['language'] == "pl_PL" || $_SESSION['_config']['language'] == "hu_HU") { + } else if($_SESSION['_config']['language'] == "pl" || + $_SESSION['_config']['language'] == "hu") { $_SESSION['_config']['recode'] = "html..ISO-8859-2"; - } else if($_SESSION['_config']['language'] == "ja_JP") { + } else if($_SESSION['_config']['language'] == "ja") { $_SESSION['_config']['recode'] = "html..SHIFT-JIS"; - } else if($_SESSION['_config']['language'] == "ru_RU") { + } else if($_SESSION['_config']['language'] == "ru") { $_SESSION['_config']['recode'] = "html..ISO-8859-5"; - } else if($_SESSION['_config']['language'] == "lt_LT") { + } else if($_SESSION['_config']['language'] == "lt") { $_SESSION['_config']['recode'] = "html..ISO-8859-13"; } @@ -183,10 +197,6 @@ bindtextdomain($domain, $_SESSION['_config']['filepath']."/locale"); textdomain($domain); - //if($_SESSION['profile']['id'] == -1) - // echo $_SESSION['_config']['language']." - ".$_SESSION['_config']['filepath']."/locale"; - - if(array_key_exists('profile',$_SESSION) && is_array($_SESSION['profile']) && array_key_exists('id',$_SESSION['profile']) && $_SESSION['profile']['id'] > 0) { $locked = mysql_fetch_assoc(mysql_query("select `locked` from `users` where `id`='".$_SESSION['profile']['id']."'")); diff --git a/locale/.gitignore b/locale/.gitignore index 94fd7c6..ac93223 100644 --- a/locale/.gitignore +++ b/locale/.gitignore @@ -1,5 +1,6 @@ # Language files are imported from translingo # => Ignore them -# Use make.php if you need new ones +# Use make if you need new ones *.po +*.pot *.mo diff --git a/locale/Makefile b/locale/Makefile new file mode 100644 index 0000000..b703fb2 --- /dev/null +++ b/locale/Makefile @@ -0,0 +1,184 @@ +# +# This Makefile will download the translations from our translation server (if +# they don't exist yet) and compile them. Try target help for more information +# + +################################################################################ +### Download ### +################################################################################ + +DOWNLOAD_SERVER := translations.cacert.org +PO_URL_TEMPLATE := http://$(DOWNLOAD_SERVER)/export/cacert/%/messages.po + +# Only use languages that have 10% or more of translated strings +AUTO_LANGS := \ +en \ +de \ +nl \ +pt_BR \ +fr \ +sv \ +it \ +es \ +hu \ +fi \ +ja \ +bg \ +pt \ +da \ +pl \ +zh_CN \ +ru \ +lv \ +cs \ +zh_TW \ +el \ +tr \ +ar \ + +LANGS := \ +ar \ +bg \ +cs \ +da \ +de \ +el \ +en \ +es \ +fa \ +fi \ +fr \ +he \ +hr \ +hu \ +id \ +is \ +it \ +ja \ +ka \ +ko \ +lv \ +nb \ +nl \ +pl \ +pt \ +pt_BR \ +ro \ +ru \ +sl \ +sv \ +th \ +tr \ +uk \ +zh_CN \ +zh_TW \ + + +PO_FILE_TEMPLATE := %/messages.po +MO_FILE_TEMPLATE := %/LC_MESSAGES/messages.mo + + +# target: all - Build locales downloading po files +.PHONY: all +all: $(AUTO_LANGS) + + +# target: help - Display callable targets +.PHONY: help +help: + @egrep "^# target:" [Mm]akefile + + +# target: clean - remove the build directories +RM := rm -rf +.PHONY: clean +clean: + -$(RM) $(LANGS:%=%/) + + +# target: - build this particular language +.PHONY: $(LANGS) +$(LANGS): %: $(MO_FILE_TEMPLATE) + + +$(LANGS:%=$(MO_FILE_TEMPLATE)): $(MO_FILE_TEMPLATE): $(PO_FILE_TEMPLATE) + mkdir -p $(@D) +#filter obsolete translations + grep --invert-match '^#~ ' $< | \ + msgfmt --check --output-file $@ - + + +.PHONY: $(LANGS:%=$(PO_FILE_TEMPLATE)) +$(LANGS:%=$(PO_FILE_TEMPLATE)): + mkdir -p $(@D) + wget --output-document - '$(@:$(PO_FILE_TEMPLATE)=$(PO_URL_TEMPLATE))' | \ + # convert UTF-8 characters to HTML entities \ + php -r 'while (!feof(STDIN)) echo mb_convert_encoding(fgets(STDIN), "HTML-ENTITIES", "UTF-8");' \ + > $@ + + + + +################################################################################ +### Upload ### +################################################################################ + +UPLOAD_SERVER := $(DOWNLOAD_SERVER) +SSH_USER := critical +SSH_OPTIONS := +SCP_OPTIONS := $(SSH_OPTIONS) + +FILE_OWNER := www-data + +POT_UPLOAD_PATH := /var/www/Pootle/po/cacert/templates/messages.pot +MANAGE_PY := /var/www/Pootle/manage.py + +VERSION := Production +DESCRITPION := LibreSSL - CAcert web application (localisation files) +COPYRIGHT_YEAR := 2004-$(shell date +\%Y) +PACKAGE := LibreSSL + +GETTEXT_FILE_PATTERN := \ +../CommModule/client.pl \ +../includes/*.php \ +../includes/*/*.php \ +../pages/*/*.php \ +../scripts/*.php \ +../www/*.php \ +../www/*/*.php \ +# ../tverify/*.php \ +# ../tverify/*/*.php \ + +GETTEXT_FILES := $(wildcard $(GETTEXT_FILE_PATTERN)) + +# target: template - create the gettext template file, if you want to upload it +# target: onto the translation server you can directly use the +# target: target "upload" +.PHONY: template +template: messages.pot + +# target: template.clean - remove anything that was created during the build of +# target: the template file +.PHONY: template.clean +template.clean: + -$(RM) messages.pot + + +# target: upload - upload the template to the translation server +.PHONY: upload +upload: messages.pot + scp $(SCP_OPTIONS) messages.pot $(SSH_USER)@$(UPLOAD_SERVER):$(POT_UPLOAD_PATH) + ssh $(SSH_OPTIONS) $(SSH_USER)@$(UPLOAD_SERVER) "sudo -u $(FILE_OWNER) pootle-update cacert" + +# target: upload.clean - remove anything that was created during the upload +.PHONY: upload.clean +upload.clean: template.clean + +messages.pot: $(GETTEXT_FILES) + xgettext --output - --sort-by-file --copyright-holder "CAcert Inc." \ + --package-name "CAcert" --package-version "$(VERSION)" \ + --msgid-bugs-address "translations-admin@cacert.org" $^ | \ + # replace place holders in the lines before the first msgid\ + sed '1,/^msgid/ { s/SOME DESCRIPTIVE TITLE/$(DESCRITPION)/; s/YEAR/$(COPYRIGHT_YEAR)/; s/PACKAGE/$(PACKAGE)/ }' \ + > $@ + diff --git a/locale/make.php b/locale/make.php deleted file mode 100755 index 2ffd5a0..0000000 --- a/locale/make.php +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/php -q - "bg_BG", "da" => "da_DK", "de" => "de_DE", "es" => "es_ES", - "fr" => "fr_FR", "fi" => "fi_FI", "he" => "he_IL", "hr" => "hr_HR", - "hu" => "hu_HU", "id" => "id_ID", "it" => "it_IT", "ja" => "ja_JP", - "nl" => "nl_NL", "lv" => "lv_LV", "pt" => "pt_PT", "pt_BR" => "pt_BR", - "ro" => "ro_RO", "ru" => "ru_RU", "fa" => "fa_IR", "sv" => "sv_SE", - "tr" => "tr_TR", "zh_CN" => "zh_CN", "zh_TW" => "zh_TW", "ar" => "ar_SY", - "el" => "el_GR", "tl" => "tl_PH", "pl" => "pl_PL", "cs" => "cs_CZ", - "ka" => "ka_GE", "is" => "is_IS", "ko" => "ko_KR", "nb" => "nb_NO", - "sl" => "sl_SI", "th" => "th_TH", "uk" => "uk_UA"); - - if($argc > 1) - { - foreach($argv as $key) - { - $val = $lang[$key]; - if($val != "") - { - echo `mkdir -p $key/LC_MESSAGES/`; - $do = `wget -O $key/messages.po "http://translingo.cacert.org/export2.php?pid=1&editlanguage=$val" 2>&1`; -echo $do; - $do = `msgfmt -o $key/LC_MESSAGES/messages.mo $key/messages.po 2>&1`; -echo $do; - } - } - } else { - foreach($lang as $key => $val) - { - echo `mkdir -p $key/LC_MESSAGES/`; - $do = `wget -O $key/messages.po "http://translingo.cacert.org/export2.php?pid=1&editlanguage=$val" 2>&1`; -echo $do; - $do = `msgfmt -o $key/LC_MESSAGES/messages.mo $key/messages.po 2>&1`; -echo $do; - } - } -?> diff --git a/password.dat.sample b/password.dat.sample deleted file mode 100644 index f9bbb55..0000000 --- a/password.dat.sample +++ /dev/null @@ -1,2 +0,0 @@ -$translingo_password = 'ThePassword'; -$translingo_account = 'TheAccount'; -- cgit v1.2.1 From 5d77aa2cc71fdf038c6ea67eb282e7d8edd1fa4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20T=C3=A4nzer?= Date: Wed, 28 Sep 2011 04:10:33 +0200 Subject: bug 985: map language to the right locale and other fixes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - map from two letter to five letter code - if lang is given as parameter but $_SESSION['_config']['language'] has already been set also go into the translation handling code - preg_filter() is PHP >= 5.3 Signed-off-by: Michael Tänzer --- includes/general.php | 73 ++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 59 insertions(+), 14 deletions(-) diff --git a/includes/general.php b/includes/general.php index 0231b21..5c1b3f2 100644 --- a/includes/general.php +++ b/includes/general.php @@ -102,7 +102,9 @@ - if(!(array_key_exists('language',$_SESSION['_config']) && $_SESSION['_config']['language'] != "")) + if((array_key_exists("lang",$_REQUEST) && trim($_REQUEST["lang"]) != "") || + !(array_key_exists('language',$_SESSION['_config']) && + $_SESSION['_config']['language'] != "") ) { $languages=array(); @@ -135,32 +137,75 @@ // remove any non-conforming values (that's why we don't need to // mysql_real_escape() or escapeshellarg() but take care of the *) // spec: ( ( 1*8ALPHA *( "-" 1*8ALPHA ) ) | "*" ) - $languages = preg_filter('/^(?:[a-zA-Z]{1,8}(?:-[a-zA-Z]{1,8})*|\*)$/', - '$0', $languages); + function is_language_range($candidate) + { + return preg_match('/^(?:[a-zA-Z]{1,8}(?:-[a-zA-Z]{1,8})*|\*)$/', + $candidate) === 1; + } + $languages = array_filter($languages, "is_language_range"); krsort($languages, SORT_NUMERIC); - $all_translations = scandir($_SESSION['_config']['filepath']."/locale/"); + $all_translations = array( + "ar" => "ar_JO", + "bg" => "bg_BG", + "cs" => "cs_CZ", + "da" => "da_DK", + "de" => "de_DE", + "el" => "el_GR", + "en" => "en_US", + "es" => "es_ES", + "fa" => "fa_IR", + "fi" => "fi_FI", + "fr" => "fr_FR", + "he" => "he_IL", + "hr" => "hr_HR", + "hu" => "hu_HU", + "id" => "id_ID", + "is" => "is_IS", + "it" => "it_IT", + "ja" => "ja_JP", + "ka" => "ka_GE", + "ko" => "ko_KR", + "lv" => "lv_LV", + "nb" => "nb_NO", + "nl" => "nl_NL", + "pl" => "pl_PL", + "pt" => "pt_PT", + "pt_BR" => "pt_BR", + "ro" => "ro_RO", + "ru" => "ru_RU", + "sl" => "sl_SI", + "sv" => "sv_SE", + "th" => "th_TH", + "tr" => "tr_TR", + "uk" => "uk_UA", + "zh_CN" => "zh_CN", + "zh_TW" => "zh_TW", + ); + foreach($languages as $qvalue => $lang) { $lang = strtr($lang, '-', '_'); $lang_length = strlen($lang); + $chosen_locale = ""; $chosen_translation = ""; - foreach ($all_translations as $translation) + foreach ($all_translations as $translation => $locale) { $translation_lower = strtolower($translation); if ($translation_lower === $lang || - substr($translation, 0, $lang_length + 1) === $lang.'_') + substr($translation_lower, 0, $lang_length + 1) === $lang.'_') { $chosen_translation = $translation; + $chosen_locale = $locale; break; } } - if ($chosen_translation !== "") + if ($chosen_locale !== "") { if(file_exists($_SESSION['_config']['filepath']."/locale/$chosen_translation/LC_MESSAGES/messages.mo")) { - $_SESSION['_config']['language'] = $lang; + $_SESSION['_config']['language'] = $chosen_locale; break; } } @@ -170,7 +215,7 @@ !array_key_exists('language',$_SESSION['_config']) || $_SESSION['_config']['language'] == "" ) { - $_SESSION['_config']['language'] = "en"; + $_SESSION['_config']['language'] = "en_US"; trigger_error('$_SESSION[\'_config\'][\'language\'] was not set after '. 'the translation search', E_USER_WARNING); } @@ -180,14 +225,14 @@ $_SESSION['_config']['language'] === "zh_TW") { $_SESSION['_config']['recode'] = "html..gb2312"; - } else if($_SESSION['_config']['language'] == "pl" || - $_SESSION['_config']['language'] == "hu") { + } else if($_SESSION['_config']['language'] == "pl_PL" || + $_SESSION['_config']['language'] == "hu_HU") { $_SESSION['_config']['recode'] = "html..ISO-8859-2"; - } else if($_SESSION['_config']['language'] == "ja") { + } else if($_SESSION['_config']['language'] == "ja_JP") { $_SESSION['_config']['recode'] = "html..SHIFT-JIS"; - } else if($_SESSION['_config']['language'] == "ru") { + } else if($_SESSION['_config']['language'] == "ru_RU") { $_SESSION['_config']['recode'] = "html..ISO-8859-5"; - } else if($_SESSION['_config']['language'] == "lt") { + } else if($_SESSION['_config']['language'] == "lt_LT") { $_SESSION['_config']['recode'] = "html..ISO-8859-13"; } -- cgit v1.2.1 From d581655fb544070921a38ac92efb30422f7560d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20T=C3=A4nzer?= Date: Sun, 16 Oct 2011 04:53:08 +0200 Subject: bug 985: Factor out language handling into a separate class, also fix language handling for Internet Explorer. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit TODO: - replace all uses of $_SESSION['_config']['language'] and $_SESSION['_config']['translations'] with the appropriate calls to the new class - adjust character handling in the PDF generation routines - probably more Signed-off-by: Michael Tänzer --- includes/general.php | 173 +------------------------- includes/lib/l10n.php | 331 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 333 insertions(+), 171 deletions(-) create mode 100644 includes/lib/l10n.php diff --git a/includes/general.php b/includes/general.php index 5c1b3f2..d608d2d 100644 --- a/includes/general.php +++ b/includes/general.php @@ -39,6 +39,7 @@ require_once($_SESSION['_config']['filepath']."/includes/mysql.php"); require_once($_SESSION['_config']['filepath'].'/includes/lib/account.php'); + require_once($_SESSION['_config']['filepath'].'/includes/lib/l10n.php'); if(array_key_exists('HTTP_HOST',$_SERVER) && $_SERVER['HTTP_HOST'] != $_SESSION['_config']['normalhostname'] && @@ -70,177 +71,7 @@ } } - - /////////////////////// - // Language Handling // - /////////////////////// - - $_SESSION['_config']['translations'] = array( - "ar" => "العربية", - "bg" => "Български", - "cs" => "Čeština", - "da" => "Dansk", - "de" => "Deutsch", - "el" => "Ελληνικά", - "en" => "English", - "es" => "Español", - "fi" => "Suomi", - "fr" => "Français", - "hu" => "Magyar", - "it" => "Italiano", - "ja" => "日本語", - "lv" => "Latviešu", - "nl" => "Nederlands", - "pl" => "Polski", - "pt" => "Português", - "pt-br" => "Português Brasileiro", - "ru" => "Русский", - "sv" => "Svenska", - "tr" => "Türkçe", - "zh-cn" => "中文(简体)", - "zh-tw" => "中文(臺灣)"); - - - - if((array_key_exists("lang",$_REQUEST) && trim($_REQUEST["lang"]) != "") || - !(array_key_exists('language',$_SESSION['_config']) && - $_SESSION['_config']['language'] != "") ) - { - $languages=array(); - - // parse Accept-Language header - $bits = explode(",", strtolower(str_replace(" ", "", array_key_exists('HTTP_ACCEPT_LANGUAGE',$_SERVER)?$_SERVER['HTTP_ACCEPT_LANGUAGE']:""))); - foreach($bits as $lang) - { - $b = explode(";", $lang); - if(count($b)>1 && substr($b[1], 0, 2) == "q=") - $c = floatval(substr($b[1], 2)); - else - $c = 1; - - if ($c != 0) - { - $languages["$c"] = trim($b[0]); - } - } - - // check if there is an explicit language given as parameter - if(array_key_exists("lang",$_REQUEST) && trim($_REQUEST["lang"]) != "") - { - // higher priority as those values in the header - $languages["2.0"] = strtolower(trim($_REQUEST["lang"])); - } - - // fallback, qvalues may only have three digits after the . - $languages["0.0005"] = "en"; - - // remove any non-conforming values (that's why we don't need to - // mysql_real_escape() or escapeshellarg() but take care of the *) - // spec: ( ( 1*8ALPHA *( "-" 1*8ALPHA ) ) | "*" ) - function is_language_range($candidate) - { - return preg_match('/^(?:[a-zA-Z]{1,8}(?:-[a-zA-Z]{1,8})*|\*)$/', - $candidate) === 1; - } - $languages = array_filter($languages, "is_language_range"); - - krsort($languages, SORT_NUMERIC); - - $all_translations = array( - "ar" => "ar_JO", - "bg" => "bg_BG", - "cs" => "cs_CZ", - "da" => "da_DK", - "de" => "de_DE", - "el" => "el_GR", - "en" => "en_US", - "es" => "es_ES", - "fa" => "fa_IR", - "fi" => "fi_FI", - "fr" => "fr_FR", - "he" => "he_IL", - "hr" => "hr_HR", - "hu" => "hu_HU", - "id" => "id_ID", - "is" => "is_IS", - "it" => "it_IT", - "ja" => "ja_JP", - "ka" => "ka_GE", - "ko" => "ko_KR", - "lv" => "lv_LV", - "nb" => "nb_NO", - "nl" => "nl_NL", - "pl" => "pl_PL", - "pt" => "pt_PT", - "pt_BR" => "pt_BR", - "ro" => "ro_RO", - "ru" => "ru_RU", - "sl" => "sl_SI", - "sv" => "sv_SE", - "th" => "th_TH", - "tr" => "tr_TR", - "uk" => "uk_UA", - "zh_CN" => "zh_CN", - "zh_TW" => "zh_TW", - ); - - foreach($languages as $qvalue => $lang) - { - $lang = strtr($lang, '-', '_'); - $lang_length = strlen($lang); - $chosen_locale = ""; - $chosen_translation = ""; - foreach ($all_translations as $translation => $locale) - { - $translation_lower = strtolower($translation); - if ($translation_lower === $lang || - substr($translation_lower, 0, $lang_length + 1) === $lang.'_') - { - $chosen_translation = $translation; - $chosen_locale = $locale; - break; - } - } - if ($chosen_locale !== "") - { - if(file_exists($_SESSION['_config']['filepath']."/locale/$chosen_translation/LC_MESSAGES/messages.mo")) - { - $_SESSION['_config']['language'] = $chosen_locale; - break; - } - } - } - } - if(!array_key_exists('_config',$_SESSION) || - !array_key_exists('language',$_SESSION['_config']) || - $_SESSION['_config']['language'] == "" ) - { - $_SESSION['_config']['language'] = "en_US"; - trigger_error('$_SESSION[\'_config\'][\'language\'] was not set after '. - 'the translation search', E_USER_WARNING); - } - - $_SESSION['_config']['recode'] = "html..latin-1"; - if($_SESSION['_config']['language'] === "zh_CN" || - $_SESSION['_config']['language'] === "zh_TW") - { - $_SESSION['_config']['recode'] = "html..gb2312"; - } else if($_SESSION['_config']['language'] == "pl_PL" || - $_SESSION['_config']['language'] == "hu_HU") { - $_SESSION['_config']['recode'] = "html..ISO-8859-2"; - } else if($_SESSION['_config']['language'] == "ja_JP") { - $_SESSION['_config']['recode'] = "html..SHIFT-JIS"; - } else if($_SESSION['_config']['language'] == "ru_RU") { - $_SESSION['_config']['recode'] = "html..ISO-8859-5"; - } else if($_SESSION['_config']['language'] == "lt_LT") { - $_SESSION['_config']['recode'] = "html..ISO-8859-13"; - } - - putenv("LANG=".$_SESSION['_config']['language']); - setlocale(LC_ALL, $_SESSION['_config']['language']); - $domain = 'messages'; - bindtextdomain($domain, $_SESSION['_config']['filepath']."/locale"); - textdomain($domain); + L10n::detect_language(); if(array_key_exists('profile',$_SESSION) && is_array($_SESSION['profile']) && array_key_exists('id',$_SESSION['profile']) && $_SESSION['profile']['id'] > 0) { diff --git a/includes/lib/l10n.php b/includes/lib/l10n.php new file mode 100644 index 0000000..386cece --- /dev/null +++ b/includes/lib/l10n.php @@ -0,0 +1,331 @@ + "native name of the language") + */ + public static $translations = array( + "ar" => "العربية", + "bg" => "Български", + "cs" => "Čeština", + "da" => "Dansk", + "de" => "Deutsch", + "el" => "Ελληνικά", + "en" => "English", + "es" => "Español", + "fi" => "Suomi", + "fr" => "Français", + "hu" => "Magyar", + "it" => "Italiano", + "ja" => "日本語", + "lv" => "Latviešu", + "nl" => "Nederlands", + "pl" => "Polski", + "pt" => "Português", + "pt-br" => "Português Brasileiro", + "ru" => "Русский", + "sv" => "Svenska", + "tr" => "Türkçe", + "zh-cn" => "中文(简体)", + "zh-tw" => "中文(臺灣)", + ); + + /** + * setlocale needs a language + region code for whatever reason so here's + * the mapping from a translation code to locales with the region that + * seemed the most common for this language + * + * You probably never need this. Use {@link set_translation()} to change the + * language instead of manually calling setlocale(). + * + * @var array(string => string) + */ + private static $locales = array( + "ar" => "ar_JO", + "bg" => "bg_BG", + "cs" => "cs_CZ", + "da" => "da_DK", + "de" => "de_DE", + "el" => "el_GR", + "en" => "en_US", + "es" => "es_ES", + "fa" => "fa_IR", + "fi" => "fi_FI", + "fr" => "fr_FR", + "he" => "he_IL", + "hr" => "hr_HR", + "hu" => "hu_HU", + "id" => "id_ID", + "is" => "is_IS", + "it" => "it_IT", + "ja" => "ja_JP", + "ka" => "ka_GE", + "ko" => "ko_KR", + "lv" => "lv_LV", + "nb" => "nb_NO", + "nl" => "nl_NL", + "pl" => "pl_PL", + "pt" => "pt_PT", + "pt-br" => "pt_BR", + "ro" => "ro_RO", + "ru" => "ru_RU", + "sl" => "sl_SI", + "sv" => "sv_SE", + "th" => "th_TH", + "tr" => "tr_TR", + "uk" => "uk_UA", + "zh-cn" => "zh_CN", + "zh-tw" => "zh_TW", + ); + + /** + * Auto-detects the language that should be used and sets it. Only works for + * HTTP, not in a command line script. + * + * Priority: + *
    + *
  1. explicit parameter "lang" passed in HTTP (e.g. via GET)
  2. + *
  3. existing setting in the session (stick to the setting we had before) + *
  4. + *
  5. auto-detect via the HTTP Accept-Language header sent by the user + * agent
  6. + *
+ */ + public static function detect_language() { + if ( (self::get_translation() != "") + // already set in the session? + && + !(array_key_exists("lang", $_REQUEST) && + trim($_REQUEST["lang"]) != "") + // explicit parameter? + ) + { + if ( self::set_translation(self::get_translation()) ) { + return; + } + } + + + $languages = array(); + + // parse Accept-Language header + if (array_key_exists('HTTP_ACCEPT_LANGUAGE', $_SERVER)) { + $bits = explode(",", strtolower( + str_replace(" ", "", $_SERVER['HTTP_ACCEPT_LANGUAGE']) + )); + foreach($bits as $lang) + { + $b = explode(";", $lang); + if(count($b)>1 && substr($b[1], 0, 2) == "q=") + $c = floatval(substr($b[1], 2)); + else + $c = 1; + + if ($c != 0) + { + $languages[trim($b[0])] = $c; + } + } + } + + // check if there is an explicit language given as parameter + if(array_key_exists("lang",$_REQUEST) && trim($_REQUEST["lang"]) != "") + { + // higher priority than those values in the header + $languages[strtolower(trim($_REQUEST["lang"]))] = 2.0; + } + + arsort($languages, SORT_NUMERIC); + + // this is used to be compatible with browsers like internet + // explorer which only provide the language code including the + // region not without. Also handles the fallback to English (qvalues + // may only have three digits after the .) + $fallbacks = array("en" => 0.0005); + + foreach($languages as $lang => $qvalue) + { + // ignore any non-conforming values (that's why we don't need to + // mysql_real_escape() or escapeshellarg(), but take care of + // the '*') + // spec: ( ( 1*8ALPHA *( "-" 1*8ALPHA ) ) | "*" ) + if ( preg_match('/^(?:([a-zA-Z]{1,8})(?:-[a-zA-Z]{1,8})*|\*)$/', + $lang, $matches) !== 1 ) { + continue; + } + $lang_prefix = $matches[1]; // usually two-letter language code + $fallbacks[$lang_prefix] = $qvalue; + + $chosen_translation = ""; + if ($lang === '*') { + // According to the standard '*' matches anything but any + // language explicitly specified. So in theory if there + // was an explicit mention of "en" with a lower priority + // this would be incorrect, but that's too much trouble. + $chosen_translation = "en"; + } else { + $lang_length = strlen($lang); + foreach (self::$translations as $translation => $ignore) + { + // May match exactly or on every '-' + if ( $translation === $lang || + substr($translation, 0, $lang_length + 1) + === $lang.'-' + ) + { + $chosen_translation = $translation; + break; + } + } + } + + if ($chosen_translation !== "") + { + if (self::set_translation($chosen_translation)) { + return; + } + } + } + + // No translation found yet => try the prefixes + arsort($fallbacks, SORT_NUMERIC); + foreach ($fallbacks as $lang => $qvalue) { + if (self::set_translation($chosen_translation)) { + return; + } + } + + // should not get here, as the fallback of "en" is provided and that + // should always work => log an error + trigger_error("L10n::detect_language(): could not set language", + E_USER_WARNING); + } + + /** + * Get the set translation + * + * @return string a translation code or the empty string if not set + */ + public static function get_translation() { + if (array_key_exists('language', $_SESSION['_config'])) { + return $_SESSION['_config']['language']; + } else { + return ""; + } + } + + /** + * Set the translation to use. + * + * @param string $translation_code the translation code as specified in + * the keys of {@link translations} + * + * @return bool + *
    + *
  • true if the translation has been set successfully
  • + *
  • false if the $translation_code was not contained in the white + * list or could not be set for other reasons (e.g. setlocale() + * failed because the locale has not been set up on the system - + * details will be logged)
  • + *
+ */ + public static function set_translation($translation_code) { + // check $translation_code against whitelist + if ( !array_key_exists($translation_code, self::$translations) ) { + // maybe it's a locale as previously used in the system? e.g. en_AU + if ( preg_match('/^([a-z][a-z])_([A-Z][A-Z])$/', $translation_code, + $matches) !== 1 ) { + return false; + } + + $lang_code = $matches[1]; + $region_code = strtolower($matches[2]); + + if ( array_key_exists("${lang_code}-${region_code}", + self::$translations) ) { + $translation_code = "${lang_code}-${region_code}"; + } elseif ( array_key_exists($lang_code, self::$translations) ) { + $translation_code = $lang_code; + } else { + return false; + } + } + + // map translation to locale + if ( !array_key_exists($translation_code, self::$locales) ) { + // weird. maybe you added a translation but haven't added a + // translation to locale mapping in self::locales? + trigger_error("L10n::set_translation(): could not map the ". + "translation $translation_code to a locale", E_USER_WARNING); + return false; + } + $locale = self::$locales[$translation_code]; + + // set up locale + if ( !putenv("LANG=$locale") ) { + trigger_error("L10n::set_translation(): could not set the ". + "environment variable LANG to $locale", E_USER_WARNING); + return false; + } + if ( !setlocale(LC_ALL, $locale) ) { + trigger_error("L10n::set_translation(): could not setlocale() ". + "LC_ALL to $locale", E_USER_WARNING); + return false; + } + + // configure gettext + $domain = 'messages'; + bindtextdomain($domain, $_SESSION['_config']['filepath']."/locale"); + textdomain($domain); + + + // save the setting + $_SESSION['_config']['language'] = $translation_code; + + + // Set up the recode settings needed e.g. in PDF creation + $_SESSION['_config']['recode'] = "html..latin-1"; + + if($translation_code === "zh-cn" || $translation_code === "zh-tw") + { + $_SESSION['_config']['recode'] = "html..gb2312"; + + } else if($translation_code === "pl" || $translation_code === "hu") { + $_SESSION['_config']['recode'] = "html..ISO-8859-2"; + + } else if($translation_code === "ja") { + $_SESSION['_config']['recode'] = "html..SHIFT-JIS"; + + } else if($translation_code === "ru") { + $_SESSION['_config']['recode'] = "html..ISO-8859-5"; + + } else if($translation_code == "lt") { // legacy, keep for reference + $_SESSION['_config']['recode'] = "html..ISO-8859-13"; + + } + } +} \ No newline at end of file -- cgit v1.2.1 From 6e0ae5b60fdb53fccfa90519522fb9b1cbd44e45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20T=C3=A4nzer?= Date: Sun, 16 Oct 2011 05:07:49 +0200 Subject: bug 985: doh, actually return something MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Michael Tänzer --- includes/lib/l10n.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/includes/lib/l10n.php b/includes/lib/l10n.php index 386cece..58b6859 100644 --- a/includes/lib/l10n.php +++ b/includes/lib/l10n.php @@ -327,5 +327,7 @@ class L10n { $_SESSION['_config']['recode'] = "html..ISO-8859-13"; } + + return true; } } \ No newline at end of file -- cgit v1.2.1 From 147cce7acd3ce673c494dc9b30f36b3d5554abea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20T=C3=A4nzer?= Date: Sun, 16 Oct 2011 06:09:25 +0200 Subject: bug 985: replace occurences of $_SESSION['_config']['translations'] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit this includes a little rewrite of reminder handling Signed-off-by: Michael Tänzer --- includes/account.php | 3 ++- includes/general_stuff.php | 4 +++- pages/account/41.php | 11 +++++++---- pages/wot/5.php | 3 ++- pages/wot/9.php | 9 ++++++--- www/wot.php | 47 ++++++++++++++++++++++------------------------ 6 files changed, 42 insertions(+), 35 deletions(-) diff --git a/includes/account.php b/includes/account.php index 24c61d8..ebae1f6 100644 --- a/includes/account.php +++ b/includes/account.php @@ -16,6 +16,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ require_once("../includes/loggedin.php"); + require_once("../includes/lib/l10n.php"); loadem("account"); @@ -2345,7 +2346,7 @@ { csrf_check("mainlang"); $lang = mysql_real_escape_string($_REQUEST['lang']); - foreach($_SESSION['_config']['translations'] as $key => $val) + foreach(L10n::$translations as $key => $val) { if($key == $lang) { diff --git a/includes/general_stuff.php b/includes/general_stuff.php index 088c39e..b4795e0 100644 --- a/includes/general_stuff.php +++ b/includes/general_stuff.php @@ -16,6 +16,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +require_once($_SESSION['_config']['filepath'].'/includes/lib/l10n.php'); + if(!function_exists("showheader")) { function showbodycontent($title = "CAcert.org", $title2 = "") @@ -60,7 +62,7 @@ google_color_border = "FFFFFF";