Move the language module from where i was hiding it in contrib to the main repository
This commit is contained in:
parent
7ce96db688
commit
5bbb4358c2
@ -1,131 +0,0 @@
|
||||
<?php defined("SYSPATH") or die("No direct script access.");
|
||||
/**
|
||||
* Gallery - a web based photo album viewer and editor
|
||||
* Copyright (C) 2000-2010 Bharat Mediratta
|
||||
*
|
||||
* 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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
class Admin_Languages_Controller extends Admin_Controller {
|
||||
public function index($share_translations_form=null) {
|
||||
$v = new Admin_View("admin.html");
|
||||
$v->page_title = t("Languages and translations");
|
||||
$v->content = new View("admin_languages.html");
|
||||
$v->content->available_locales = locales::available();
|
||||
$v->content->installed_locales = locales::installed();
|
||||
$v->content->default_locale = module::get_var("gallery", "default_locale");
|
||||
|
||||
if (empty($share_translations_form)) {
|
||||
$share_translations_form = $this->_share_translations_form();
|
||||
}
|
||||
$v->content->share_translations_form = $share_translations_form;
|
||||
$this->_outgoing_translations_count();
|
||||
print $v;
|
||||
}
|
||||
|
||||
public function save() {
|
||||
access::verify_csrf();
|
||||
|
||||
$input = Input::instance();
|
||||
locales::update_installed($input->post("installed_locales"));
|
||||
|
||||
$installed_locales = array_keys(locales::installed());
|
||||
$new_default_locale = $input->post("default_locale");
|
||||
if (!in_array($new_default_locale, $installed_locales)) {
|
||||
if (!empty($installed_locales)) {
|
||||
$new_default_locale = $installed_locales[0];
|
||||
} else {
|
||||
$new_default_locale = "en_US";
|
||||
}
|
||||
}
|
||||
module::set_var("gallery", "default_locale", $new_default_locale);
|
||||
|
||||
print json_encode(array("result" => "success"));
|
||||
}
|
||||
|
||||
public function share() {
|
||||
access::verify_csrf();
|
||||
|
||||
$form = $this->_share_translations_form();
|
||||
if (!$form->validate()) {
|
||||
// Show the page with form errors
|
||||
return $this->index($form);
|
||||
}
|
||||
|
||||
if (Input::instance()->post("share")) {
|
||||
l10n_client::submit_translations();
|
||||
message::success(t("Translations submitted"));
|
||||
} else {
|
||||
return $this->_save_api_key($form);
|
||||
}
|
||||
url::redirect("admin/languages");
|
||||
}
|
||||
|
||||
private function _save_api_key($form) {
|
||||
$new_key = $form->sharing->api_key->value;
|
||||
if ($new_key && !l10n_client::validate_api_key($new_key)) {
|
||||
$form->sharing->api_key->add_error("invalid", 1);
|
||||
$valid = false;
|
||||
} else {
|
||||
$valid = true;
|
||||
}
|
||||
|
||||
if ($valid) {
|
||||
$old_key = l10n_client::api_key();
|
||||
l10n_client::api_key($new_key);
|
||||
if ($old_key && !$new_key) {
|
||||
message::success(t("Your API key has been cleared."));
|
||||
} else if ($old_key && $new_key && $old_key != $new_key) {
|
||||
message::success(t("Your API key has been changed."));
|
||||
} else if (!$old_key && $new_key) {
|
||||
message::success(t("Your API key has been saved."));
|
||||
} else if ($old_key && $new_key && $old_key == $new_key) {
|
||||
message::info(t("Your API key was not changed."));
|
||||
}
|
||||
|
||||
log::success(t("gallery"), t("l10n_client API key changed."));
|
||||
url::redirect("admin/languages");
|
||||
} else {
|
||||
// Show the page with form errors
|
||||
$this->index($form);
|
||||
}
|
||||
}
|
||||
|
||||
private function _outgoing_translations_count() {
|
||||
return ORM::factory("outgoing_translation")->count_all();
|
||||
}
|
||||
|
||||
private function _share_translations_form() {
|
||||
$form = new Forge("admin/languages/share", "", "post", array("id" => "g-share-translations-form"));
|
||||
$group = $form->group("sharing")
|
||||
->label(t("Sharing your own translations with the Gallery community is easy. Please do!"));
|
||||
$api_key = l10n_client::api_key();
|
||||
$server_link = l10n_client::server_api_key_url();
|
||||
$group->input("api_key")
|
||||
->label(empty($api_key)
|
||||
? t("This is a unique key that will allow you to send translations to the remote
|
||||
server. To get your API key go to %server-link.",
|
||||
array("server-link" => html::mark_clean(html::anchor($server_link))))
|
||||
: t("API key"))
|
||||
->value($api_key)
|
||||
->error_messages("invalid", t("The API key you provided is invalid."));
|
||||
$group->submit("save")->value(t("Save settings"));
|
||||
if ($api_key && $this->_outgoing_translations_count()) {
|
||||
// TODO: UI improvement: hide API key / save button when API key is set.
|
||||
$group->submit("share")->value(t("Submit translations"));
|
||||
}
|
||||
return $form;
|
||||
}
|
||||
}
|
||||
|
@ -1,179 +0,0 @@
|
||||
<?php defined("SYSPATH") or die("No direct script access.");
|
||||
/**
|
||||
* Gallery - a web based photo album viewer and editor
|
||||
* Copyright (C) 2000-2010 Bharat Mediratta
|
||||
*
|
||||
* 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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
class L10n_Client_Controller extends Controller {
|
||||
public function save() {
|
||||
access::verify_csrf();
|
||||
if (!identity::active_user()->admin) {
|
||||
access::forbidden();
|
||||
}
|
||||
|
||||
$locale = Gallery_I18n::instance()->locale();
|
||||
$input = Input::instance();
|
||||
$key = $input->post("l10n-message-key");
|
||||
|
||||
$root_message = ORM::factory("incoming_translation")
|
||||
->where("key", "=", $key)
|
||||
->where("locale", "=", "root")
|
||||
->find();
|
||||
|
||||
if (!$root_message->loaded()) {
|
||||
throw new Exception("@todo bad request data / illegal state");
|
||||
}
|
||||
$is_plural = Gallery_I18n::is_plural_message(unserialize($root_message->message));
|
||||
|
||||
$is_empty = true;
|
||||
if ($is_plural) {
|
||||
$plural_forms = l10n_client::plural_forms($locale);
|
||||
$translation = array();
|
||||
foreach($plural_forms as $plural_form) {
|
||||
$value = $input->post("l10n-edit-plural-translation-$plural_form");
|
||||
if (null === $value || !is_string($value)) {
|
||||
throw new Exception("@todo bad request data");
|
||||
}
|
||||
$translation[$plural_form] = $value;
|
||||
$is_empty = $is_empty && empty($value);
|
||||
}
|
||||
} else {
|
||||
$translation = $input->post("l10n-edit-translation");
|
||||
$is_empty = empty($translation);
|
||||
if (null === $translation || !is_string($translation)) {
|
||||
throw new Exception("@todo bad request data");
|
||||
}
|
||||
}
|
||||
|
||||
$entry = ORM::factory("outgoing_translation")
|
||||
->where("key", "=", $key)
|
||||
->where("locale", "=", $locale)
|
||||
->find();
|
||||
|
||||
if ($is_empty) {
|
||||
if ($entry->loaded()) {
|
||||
$entry->delete();
|
||||
}
|
||||
} else {
|
||||
if (!$entry->loaded()) {
|
||||
$entry->key = $key;
|
||||
$entry->locale = $locale;
|
||||
$entry->message = $root_message->message;
|
||||
$entry->base_revision = null;
|
||||
}
|
||||
|
||||
$entry->translation = serialize($translation);
|
||||
|
||||
$entry_from_incoming = ORM::factory("incoming_translation")
|
||||
->where("key", "=", $key)
|
||||
->where("locale", "=", $locale)
|
||||
->find();
|
||||
|
||||
if (!$entry_from_incoming->loaded()) {
|
||||
$entry->base_revision = $entry_from_incoming->revision;
|
||||
}
|
||||
|
||||
$entry->save();
|
||||
}
|
||||
|
||||
Gallery_I18n::clear_cache($locale);
|
||||
|
||||
print json_encode(new stdClass());
|
||||
}
|
||||
|
||||
public function toggle_l10n_mode() {
|
||||
access::verify_csrf();
|
||||
if (!identity::active_user()->admin) {
|
||||
access::forbidden();
|
||||
}
|
||||
|
||||
$session = Session::instance();
|
||||
$l10n_mode = $session->get("l10n_mode", false);
|
||||
$session->set("l10n_mode", !$l10n_mode);
|
||||
|
||||
$redirect_url = "admin/languages";
|
||||
if (!$l10n_mode) {
|
||||
$redirect_url .= "#l10n-client";
|
||||
}
|
||||
|
||||
url::redirect($redirect_url);
|
||||
}
|
||||
|
||||
private static function _l10n_client_search_form() {
|
||||
$form = new Forge("#", "", "post", array("id" => "g-l10n-search-form"));
|
||||
$group = $form->group("l10n_search");
|
||||
$group->input("l10n-search")->id("g-l10n-search");
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
public static function l10n_form() {
|
||||
if (Input::instance()->get("show_all_l10n_messages")) {
|
||||
$calls = array();
|
||||
foreach (db::build()
|
||||
->select("key", "message")
|
||||
->from("incoming_translations")
|
||||
->where("locale", "=", "root")
|
||||
->execute() as $row) {
|
||||
$calls[$row->key] = array(unserialize($row->message), array());
|
||||
}
|
||||
} else {
|
||||
$calls = Gallery_I18n::instance()->call_log();
|
||||
}
|
||||
$locale = Gallery_I18n::instance()->locale();
|
||||
|
||||
if ($calls) {
|
||||
$translations = array();
|
||||
foreach (db::build()
|
||||
->select("key", "translation")
|
||||
->from("incoming_translations")
|
||||
->where("locale", "=", $locale)
|
||||
->execute() as $row) {
|
||||
$translations[$row->key] = unserialize($row->translation);
|
||||
}
|
||||
// Override incoming with outgoing...
|
||||
foreach (db::build()
|
||||
->select("key", "translation")
|
||||
->from("outgoing_translations")
|
||||
->where("locale", "=", $locale)
|
||||
->execute() as $row) {
|
||||
$translations[$row->key] = unserialize($row->translation);
|
||||
}
|
||||
|
||||
$string_list = array();
|
||||
$cache = array();
|
||||
foreach ($calls as $key => $call) {
|
||||
list ($message, $options) = $call;
|
||||
// Ensure that the message is in the DB
|
||||
l10n_scanner::process_message($message, $cache);
|
||||
// Note: Not interpolating placeholders for the actual translation input field.
|
||||
// TODO: Might show a preview w/ interpolations (using $options)
|
||||
$translation = isset($translations[$key]) ? $translations[$key] : '';
|
||||
$string_list[] = array('source' => $message,
|
||||
'key' => $key,
|
||||
'translation' => $translation);
|
||||
}
|
||||
|
||||
$v = new View('l10n_client.html');
|
||||
$v->string_list = $string_list;
|
||||
$v->l10n_search_form = self::_l10n_client_search_form();
|
||||
$v->plural_forms = l10n_client::plural_forms($locale);
|
||||
return $v;
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
}
|
@ -1,51 +0,0 @@
|
||||
<?php defined("SYSPATH") or die("No direct script access.");/**
|
||||
* Gallery - a web based photo album viewer and editor
|
||||
* Copyright (C) 2000-2010 Bharat Mediratta
|
||||
*
|
||||
* 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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
class language_Controller extends Controller {
|
||||
public function index() {
|
||||
print $this->_get_form();
|
||||
}
|
||||
|
||||
public function handler() {
|
||||
access::verify_csrf();
|
||||
|
||||
$form = $this->_get_form();
|
||||
if ($form->validate()) {
|
||||
// @todo process the admin form
|
||||
|
||||
message::success(t("language Processing Successfully"));
|
||||
|
||||
print json_encode(
|
||||
array("result" => "success"));
|
||||
} else {
|
||||
print json_encode(
|
||||
array("result" => "error",
|
||||
"form" => $form->__toString()));
|
||||
}
|
||||
}
|
||||
|
||||
private function _get_form() {
|
||||
$form = new Forge("language/handler", "", "post",
|
||||
array("id" => "g-language-form"));
|
||||
$group = $form->group("group")->label(t("language Handler"));
|
||||
$group->input("text")->label(t("Text"))->rules("required");
|
||||
$group->submit("submit")->value(t("Submit"));
|
||||
|
||||
return $form;
|
||||
}
|
||||
}
|
@ -1,206 +0,0 @@
|
||||
/**
|
||||
* TODO(andy_st): Add original copyright notice from Drupal l10_client.
|
||||
* TODO(andy_st): Add G3 copyright notice.
|
||||
* TODO(andy_st): clean up formatting to match our other CSS files.
|
||||
*/
|
||||
|
||||
/* $Id: l10n_client.css,v 1.6 2008/09/09 10:48:20 goba Exp $ */
|
||||
|
||||
/* width percentages add to 99% rather than 100% to prevent float
|
||||
overflows from occurring in an unnamed browser that can't decide
|
||||
how it wants to round. */
|
||||
|
||||
/* l10n_client container */
|
||||
#l10n-client {
|
||||
text-align:left;
|
||||
z-index:99;
|
||||
line-height:1em;
|
||||
color:#000; background:#fff;
|
||||
position:fixed;
|
||||
width:100%; height: 2em;
|
||||
bottom:0px; left:0px;
|
||||
overflow:hidden;}
|
||||
|
||||
* html #l10n-client {
|
||||
position:static;}
|
||||
|
||||
#l10n-client-string-select .string-list,
|
||||
#l10n-client-string-editor .source,
|
||||
#l10n-client-string-editor .editor {
|
||||
height:20em;}
|
||||
|
||||
#l10n-client .labels {
|
||||
overflow:hidden;
|
||||
position:relative;
|
||||
height:2em;
|
||||
color:#fff;
|
||||
background:#37a;}
|
||||
|
||||
#l10n-client .labels .label {
|
||||
display:none;}
|
||||
|
||||
/* Panel toggle button (span) */
|
||||
#l10n-client-toggler {
|
||||
cursor:pointer;
|
||||
display:block;
|
||||
position:absolute; right:0em;
|
||||
height:2em; line-height:2em;
|
||||
text-align:center; background:#000;
|
||||
}
|
||||
#l10n-client-toggler a {
|
||||
font-size: 1em;
|
||||
padding: .5em;
|
||||
}
|
||||
#l10n-client-toggler #g-minimize-l10n {
|
||||
border-right: 1px solid #ffffff;
|
||||
}
|
||||
|
||||
/* Panel labels */
|
||||
#l10n-client h2 {
|
||||
border-left:1px solid #fff;
|
||||
height:1em; line-height:1em;
|
||||
padding: .5em; margin:0px;
|
||||
font-size:1em;
|
||||
}
|
||||
|
||||
#l10n-client .strings h2 {
|
||||
border:0px;}
|
||||
|
||||
/* 25 + 37 + 37 = 99 */
|
||||
#l10n-client .strings {
|
||||
width:25%; float:left;}
|
||||
|
||||
#l10n-client .source {
|
||||
width:37%; float:left;}
|
||||
|
||||
#l10n-client .translation {
|
||||
width:37%; float:left;}
|
||||
|
||||
/* Translatable string list */
|
||||
#l10n-client-string-select {
|
||||
display:none;
|
||||
float:left;
|
||||
width:25%;
|
||||
direction: ltr;
|
||||
}
|
||||
|
||||
#l10n-client .string-list {
|
||||
height: 16em;
|
||||
overflow:auto;
|
||||
list-style:none; list-style-image:none;
|
||||
margin:0em; padding:0em;}
|
||||
|
||||
#l10n-client .string-list li {
|
||||
font-size:.9em;
|
||||
line-height:1.5em;
|
||||
cursor:default;
|
||||
background:transparent;
|
||||
list-style:none; list-style-image:none;
|
||||
border-bottom:1px solid #ddd;
|
||||
padding:.25em .5em;
|
||||
margin:0em;}
|
||||
|
||||
/* Green for translated */
|
||||
#l10n-client .string-list li.translated {
|
||||
border-bottom-color:#9c3;
|
||||
background:#cf6; color:#360;}
|
||||
|
||||
#l10n-client .string-list li.translated:hover {
|
||||
background: #df8;}
|
||||
|
||||
#l10n-client .string-list li.translated:active {
|
||||
background: #9c3;}
|
||||
|
||||
#l10n-client .string-list li.hidden {
|
||||
display:none;}
|
||||
|
||||
/* Gray + Blue hover for untranslated */
|
||||
#l10n-client .string-list li.untranslated {}
|
||||
|
||||
#l10n-client .string-list li.untranslated:hover {
|
||||
background: #ace;}
|
||||
|
||||
#l10n-client .string-list li.untranslated:active {
|
||||
background: #8ac;}
|
||||
|
||||
/* Selected string is indicated by bold text */
|
||||
#l10n-client .string-list li.active {
|
||||
font-weight:bold;}
|
||||
|
||||
#l10n-client #g-l10n-search-form {
|
||||
background: #eee;
|
||||
margin: 0em;
|
||||
padding: .25em .25em;
|
||||
}
|
||||
|
||||
#l10n-client #g-l10n-search-form .form-item,
|
||||
#l10n-client #g-l10n-search-form input.form-text,
|
||||
#l10n-client #g-l10n-search-form #search-filter-go,
|
||||
#l10n-client #g-l10n-search-form #search-filter-clear {
|
||||
display:inline;
|
||||
vertical-align:middle;
|
||||
}
|
||||
|
||||
#l10n-client #g-l10n-search-form .form-item {
|
||||
margin:0em;
|
||||
padding:0em;
|
||||
}
|
||||
|
||||
#l10n-client #g-l10n-search-form fieldset {
|
||||
margin-bottom: 0;
|
||||
padding: .25em .25em;
|
||||
}
|
||||
|
||||
|
||||
#l10n-client #g-l10n-search-form input {
|
||||
width: 96.75%;
|
||||
}
|
||||
|
||||
#l10n-client #g-l10n-search-form #search-filter-clear {
|
||||
width:10%;
|
||||
margin:0em;
|
||||
}
|
||||
|
||||
#l10n-client-string-editor {
|
||||
display:none;
|
||||
float:left;
|
||||
width:74%;}
|
||||
|
||||
#l10n-client-string-editor .source {
|
||||
overflow:hidden;
|
||||
width:50%;
|
||||
float:left;
|
||||
}
|
||||
|
||||
#l10n-client-string-editor .source .source-text {
|
||||
line-height:1.5em;
|
||||
background:#eee;
|
||||
font-family: monospace;
|
||||
text-align: left;
|
||||
height:16em; margin:1em; padding:1em;
|
||||
overflow:auto;
|
||||
direction: ltr;
|
||||
}
|
||||
|
||||
#l10n-client-string-editor .translation {
|
||||
overflow-y:auto;
|
||||
overflow-x: hidden;
|
||||
height: 20em;
|
||||
width:49%;
|
||||
float: right;
|
||||
}
|
||||
|
||||
#g-l10n-client-save-form {
|
||||
padding: 0em;
|
||||
}
|
||||
|
||||
#l10n-client form ul,
|
||||
#l10n-client form li,
|
||||
#l10n-client form input[type=submit],
|
||||
#l10n-client form input[type=text] {
|
||||
display: inline ! important ;
|
||||
}
|
||||
|
||||
#l10n-client form .hidden {
|
||||
display: none;
|
||||
}
|
@ -1,312 +0,0 @@
|
||||
<?php defined("SYSPATH") or die("No direct script access.");
|
||||
/**
|
||||
* Gallery - a web based photo album viewer and editor
|
||||
* Copyright (C) 2000-2010 Bharat Mediratta
|
||||
*
|
||||
* 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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
class l10n_client_Core {
|
||||
|
||||
private static function _server_url() {
|
||||
return "http://gallery.menalto.com/index.php";
|
||||
}
|
||||
|
||||
static function server_api_key_url() {
|
||||
return self::_server_url() . "?q=translations/userkey/" .
|
||||
self::client_token();
|
||||
}
|
||||
|
||||
static function client_token() {
|
||||
return md5("l10n_client_client_token" . access::private_key());
|
||||
}
|
||||
|
||||
static function api_key($api_key=null) {
|
||||
if ($api_key !== null) {
|
||||
module::set_var("gallery", "l10n_client_key", $api_key);
|
||||
}
|
||||
return module::get_var("gallery", "l10n_client_key", "");
|
||||
}
|
||||
|
||||
static function server_uid($api_key=null) {
|
||||
$api_key = $api_key == null ? self::api_key() : $api_key;
|
||||
$parts = explode(":", $api_key);
|
||||
return empty($parts) ? 0 : $parts[0];
|
||||
}
|
||||
|
||||
private static function _sign($payload, $api_key=null) {
|
||||
$api_key = $api_key == null ? self::api_key() : $api_key;
|
||||
return md5($api_key . $payload . self::client_token());
|
||||
}
|
||||
|
||||
static function validate_api_key($api_key) {
|
||||
$version = "1.0";
|
||||
$url = self::_server_url() . "?q=translations/status";
|
||||
$signature = self::_sign($version, $api_key);
|
||||
|
||||
list ($response_data, $response_status) = remote::post(
|
||||
$url, array("version" => $version,
|
||||
"client_token" => self::client_token(),
|
||||
"signature" => $signature,
|
||||
"uid" => self::server_uid($api_key)));
|
||||
if (!remote::success($response_status)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches translations for l10n messages. Must be called repeatedly
|
||||
* until 0 is returned (which is a countdown indicating progress).
|
||||
*
|
||||
* @param $num_fetched in/out parameter to specify which batch of
|
||||
* messages to fetch translations for.
|
||||
* @return The number of messages for which we didn't fetch
|
||||
* translations for.
|
||||
*/
|
||||
static function fetch_updates(&$num_fetched) {
|
||||
$request = new stdClass();
|
||||
$request->locales = array();
|
||||
$request->messages = new stdClass();
|
||||
|
||||
$locales = locales::installed();
|
||||
foreach ($locales as $locale => $locale_data) {
|
||||
$request->locales[] = $locale;
|
||||
}
|
||||
|
||||
// See the server side code for how we arrive at this
|
||||
// number as a good limit for #locales * #messages.
|
||||
$max_messages = 2000 / count($locales);
|
||||
$num_messages = 0;
|
||||
$rows = db::build()
|
||||
->select("key", "locale", "revision", "translation")
|
||||
->from("incoming_translations")
|
||||
->order_by("key")
|
||||
->limit(1000000) // ignore, just there to satisfy SQL syntax
|
||||
->offset($num_fetched)
|
||||
->execute();
|
||||
$num_remaining = $rows->count();
|
||||
foreach ($rows as $row) {
|
||||
if (!isset($request->messages->{$row->key})) {
|
||||
if ($num_messages >= $max_messages) {
|
||||
break;
|
||||
}
|
||||
$request->messages->{$row->key} = 1;
|
||||
$num_messages++;
|
||||
}
|
||||
if (!empty($row->revision) && !empty($row->translation) &&
|
||||
isset($locales[$row->locale])) {
|
||||
if (!is_object($request->messages->{$row->key})) {
|
||||
$request->messages->{$row->key} = new stdClass();
|
||||
}
|
||||
$request->messages->{$row->key}->{$row->locale} = (int) $row->revision;
|
||||
}
|
||||
$num_fetched++;
|
||||
$num_remaining--;
|
||||
}
|
||||
// @todo Include messages from outgoing_translations?
|
||||
|
||||
if (!$num_messages) {
|
||||
return $num_remaining;
|
||||
}
|
||||
|
||||
$request_data = json_encode($request);
|
||||
$url = self::_server_url() . "?q=translations/fetch";
|
||||
list ($response_data, $response_status) = remote::post($url, array("data" => $request_data));
|
||||
if (!remote::success($response_status)) {
|
||||
throw new Exception("@todo TRANSLATIONS_FETCH_REQUEST_FAILED " . $response_status);
|
||||
}
|
||||
if (empty($response_data)) {
|
||||
return $num_remaining;
|
||||
}
|
||||
|
||||
$response = json_decode($response_data);
|
||||
|
||||
// Response format (JSON payload):
|
||||
// [{key:<key_1>, translation: <JSON encoded translation>, rev:<rev>, locale:<locale>},
|
||||
// {key:<key_2>, ...}
|
||||
// ]
|
||||
foreach ($response as $message_data) {
|
||||
// @todo Better input validation
|
||||
if (empty($message_data->key) || empty($message_data->translation) ||
|
||||
empty($message_data->locale) || empty($message_data->rev)) {
|
||||
throw new Exception("@todo TRANSLATIONS_FETCH_REQUEST_FAILED: Invalid response data");
|
||||
}
|
||||
$key = $message_data->key;
|
||||
$locale = $message_data->locale;
|
||||
$revision = $message_data->rev;
|
||||
$translation = json_decode($message_data->translation);
|
||||
if (!is_string($translation)) {
|
||||
// Normalize stdclass to array
|
||||
$translation = (array) $translation;
|
||||
}
|
||||
$translation = serialize($translation);
|
||||
|
||||
// @todo Should we normalize the incoming_translations table into messages(id, key, message)
|
||||
// and incoming_translations(id, translation, locale, revision)? Or just allow
|
||||
// incoming_translations.message to be NULL?
|
||||
$locale = $message_data->locale;
|
||||
$entry = ORM::factory("incoming_translation")
|
||||
->where("key", "=", $key)
|
||||
->where("locale", "=", $locale)
|
||||
->find();
|
||||
if (!$entry->loaded()) {
|
||||
// @todo Load a message key -> message (text) dict into memory outside of this loop
|
||||
$root_entry = ORM::factory("incoming_translation")
|
||||
->where("key", "=", $key)
|
||||
->where("locale", "=", "root")
|
||||
->find();
|
||||
$entry->key = $key;
|
||||
$entry->message = $root_entry->message;
|
||||
$entry->locale = $locale;
|
||||
}
|
||||
$entry->revision = $revision;
|
||||
$entry->translation = $translation;
|
||||
$entry->save();
|
||||
}
|
||||
|
||||
return $num_remaining;
|
||||
}
|
||||
|
||||
static function submit_translations() {
|
||||
// Request format (HTTP POST):
|
||||
// client_token = <client_token>
|
||||
// uid = <l10n server user id>
|
||||
// signature = md5(user_api_key($uid, $client_token) . $data . $client_token))
|
||||
// data = // JSON payload
|
||||
//
|
||||
// {<key_1>: {message: <JSON encoded message>
|
||||
// translations: {<locale_1>: <JSON encoded translation>,
|
||||
// <locale_2>: ...}},
|
||||
// <key_2>: {...}
|
||||
// }
|
||||
|
||||
// @todo Batch requests (max request size)
|
||||
// @todo include base_revision in submission / how to handle resubmissions / edit fights?
|
||||
foreach (db::build()
|
||||
->select("key", "message", "locale", "base_revision", "translation")
|
||||
->from("outgoing_translations")
|
||||
->execute() as $row) {
|
||||
$key = $row->key;
|
||||
if (!isset($request->{$key})) {
|
||||
$request->{$key}->message = json_encode(unserialize($row->message));
|
||||
}
|
||||
$request->{$key}->translations->{$row->locale} = json_encode(unserialize($row->translation));
|
||||
}
|
||||
|
||||
// @todo reduce memory consumption, e.g. free $request
|
||||
$request_data = json_encode($request);
|
||||
$url = self::_server_url() . "?q=translations/submit";
|
||||
$signature = self::_sign($request_data);
|
||||
|
||||
list ($response_data, $response_status) = remote::post(
|
||||
$url, array("data" => $request_data,
|
||||
"client_token" => self::client_token(),
|
||||
"signature" => $signature,
|
||||
"uid" => self::server_uid()));
|
||||
|
||||
if (!remote::success($response_status)) {
|
||||
throw new Exception("@todo TRANSLATIONS_SUBMISSION_FAILED " . $response_status);
|
||||
}
|
||||
if (empty($response_data)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$response = json_decode($response_data);
|
||||
// Response format (JSON payload):
|
||||
// [{key:<key_1>, locale:<locale_1>, rev:<rev_1>, status:<rejected|accepted|pending>},
|
||||
// {key:<key_2>, ...}
|
||||
// ]
|
||||
|
||||
// @todo Move messages out of outgoing into incoming, using new rev?
|
||||
// @todo show which messages have been rejected / are pending?
|
||||
}
|
||||
|
||||
/**
|
||||
* Plural forms.
|
||||
*/
|
||||
static function plural_forms($locale) {
|
||||
$parts = explode('_', $locale);
|
||||
$language = $parts[0];
|
||||
|
||||
// Data from CLDR 1.6 (http://unicode.org/cldr/data/common/supplemental/plurals.xml).
|
||||
// Docs: http://www.unicode.org/cldr/data/charts/supplemental/language_plural_rules.html
|
||||
switch ($language) {
|
||||
case 'az':
|
||||
case 'fa':
|
||||
case 'hu':
|
||||
case 'ja':
|
||||
case 'ko':
|
||||
case 'my':
|
||||
case 'to':
|
||||
case 'tr':
|
||||
case 'vi':
|
||||
case 'yo':
|
||||
case 'zh':
|
||||
case 'bo':
|
||||
case 'dz':
|
||||
case 'id':
|
||||
case 'jv':
|
||||
case 'ka':
|
||||
case 'km':
|
||||
case 'kn':
|
||||
case 'ms':
|
||||
case 'th':
|
||||
return array('other');
|
||||
|
||||
case 'ar':
|
||||
return array('zero', 'one', 'two', 'few', 'many', 'other');
|
||||
|
||||
case 'lv':
|
||||
return array('zero', 'one', 'other');
|
||||
|
||||
case 'ga':
|
||||
case 'se':
|
||||
case 'sma':
|
||||
case 'smi':
|
||||
case 'smj':
|
||||
case 'smn':
|
||||
case 'sms':
|
||||
return array('one', 'two', 'other');
|
||||
|
||||
case 'ro':
|
||||
case 'mo':
|
||||
case 'lt':
|
||||
case 'cs':
|
||||
case 'sk':
|
||||
case 'pl':
|
||||
return array('one', 'few', 'other');
|
||||
|
||||
case 'hr':
|
||||
case 'ru':
|
||||
case 'sr':
|
||||
case 'uk':
|
||||
case 'be':
|
||||
case 'bs':
|
||||
case 'sh':
|
||||
case 'mt':
|
||||
return array('one', 'few', 'many', 'other');
|
||||
|
||||
case 'sl':
|
||||
return array('one', 'two', 'few', 'other');
|
||||
|
||||
case 'cy':
|
||||
return array('one', 'two', 'many', 'other');
|
||||
|
||||
default: // en, de, etc.
|
||||
return array('one', 'other');
|
||||
}
|
||||
}
|
||||
}
|
@ -1,153 +0,0 @@
|
||||
<?php defined("SYSPATH") or die("No direct script access.");
|
||||
/**
|
||||
* Gallery - a web based photo album viewer and editor
|
||||
* Copyright (C) 2000-2010 Bharat Mediratta
|
||||
*
|
||||
* 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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Scans all source code for messages that need to be localized.
|
||||
*/
|
||||
class l10n_scanner_Core {
|
||||
// Based on Drupal's potx module, originally written by:
|
||||
// Gbor Hojtsy http://drupal.org/user/4166
|
||||
public static $cache;
|
||||
|
||||
static function process_message($message, &$cache) {
|
||||
if (empty($cache)) {
|
||||
foreach (db::build()
|
||||
->select("key")
|
||||
->from("incoming_translations")
|
||||
->where("locale", "=", "root")
|
||||
->execute() as $row) {
|
||||
$cache[$row->key] = true;
|
||||
}
|
||||
}
|
||||
|
||||
$key = Gallery_I18n::get_message_key($message);
|
||||
if (array_key_exists($key, $cache)) {
|
||||
return $cache[$key];
|
||||
}
|
||||
|
||||
$entry = ORM::factory("incoming_translation")->where("key", "=", $key)->find();
|
||||
if (!$entry->loaded()) {
|
||||
$entry->key = $key;
|
||||
$entry->message = serialize($message);
|
||||
$entry->locale = "root";
|
||||
$entry->save();
|
||||
}
|
||||
}
|
||||
|
||||
static function scan_php_file($file, &$cache) {
|
||||
$code = file_get_contents($file);
|
||||
$raw_tokens = token_get_all($code);
|
||||
unset($code);
|
||||
|
||||
$tokens = array();
|
||||
$func_token_list = array("t" => array(), "t2" => array());
|
||||
$token_number = 0;
|
||||
// Filter out HTML / whitespace, and build a lookup for global function calls.
|
||||
foreach ($raw_tokens as $token) {
|
||||
if ((!is_array($token)) || (($token[0] != T_WHITESPACE) && ($token[0] != T_INLINE_HTML))) {
|
||||
if (is_array($token)) {
|
||||
if ($token[0] == T_STRING && in_array($token[1], array("t", "t2"))) {
|
||||
$func_token_list[$token[1]][] = $token_number;
|
||||
}
|
||||
}
|
||||
$tokens[] = $token;
|
||||
$token_number++;
|
||||
}
|
||||
}
|
||||
unset($raw_tokens);
|
||||
|
||||
if (!empty($func_token_list["t"])) {
|
||||
l10n_scanner::_parse_t_calls($tokens, $func_token_list["t"], $cache);
|
||||
}
|
||||
if (!empty($func_token_list["t2"])) {
|
||||
l10n_scanner::_parse_plural_calls($tokens, $func_token_list["t2"], $cache);
|
||||
}
|
||||
}
|
||||
|
||||
static function scan_info_file($file, &$cache) {
|
||||
$info = new ArrayObject(parse_ini_file($file), ArrayObject::ARRAY_AS_PROPS);
|
||||
foreach (array('name', 'description') as $property) {
|
||||
if (isset($info->$property)) {
|
||||
l10n_scanner::process_message($info->$property, $cache);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static function _parse_t_calls(&$tokens, &$call_list, &$cache) {
|
||||
foreach ($call_list as $index) {
|
||||
$function_name = $tokens[$index++];
|
||||
$parens = $tokens[$index++];
|
||||
$first_param = $tokens[$index++];
|
||||
$next_token = $tokens[$index];
|
||||
|
||||
if ($parens == "(") {
|
||||
if (in_array($next_token, array(")", ","))
|
||||
&& (is_array($first_param) && ($first_param[0] == T_CONSTANT_ENCAPSED_STRING))) {
|
||||
$message = self::_escape_quoted_string($first_param[1]);
|
||||
l10n_scanner::process_message($message, $cache);
|
||||
} else {
|
||||
// t() found, but inside is something which is not a string literal.
|
||||
// @todo Call status callback with error filename/line.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static function _parse_plural_calls(&$tokens, &$call_list, &$cache) {
|
||||
foreach ($call_list as $index) {
|
||||
$function_name = $tokens[$index++];
|
||||
$parens = $tokens[$index++];
|
||||
$first_param = $tokens[$index++];
|
||||
$first_separator = $tokens[$index++];
|
||||
$second_param = $tokens[$index++];
|
||||
$next_token = $tokens[$index];
|
||||
|
||||
if ($parens == "(") {
|
||||
if ($first_separator == "," && $next_token == ","
|
||||
&& is_array($first_param) && $first_param[0] == T_CONSTANT_ENCAPSED_STRING
|
||||
&& is_array($second_param) && $second_param[0] == T_CONSTANT_ENCAPSED_STRING) {
|
||||
$singular = self::_escape_quoted_string($first_param[1]);
|
||||
$plural = self::_escape_quoted_string($second_param[1]);
|
||||
l10n_scanner::process_message(array("one" => $singular, "other" => $plural), $cache);
|
||||
} else {
|
||||
// t2() found, but inside is something which is not a string literal.
|
||||
// @todo Call status callback with error filename/line.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Escape quotes in a strings depending on the surrounding
|
||||
* quote type used.
|
||||
*
|
||||
* @param $str The strings to escape
|
||||
*/
|
||||
private static function _escape_quoted_string($str) {
|
||||
$quo = substr($str, 0, 1);
|
||||
$str = substr($str, 1, -1);
|
||||
if ($quo == '"') {
|
||||
$str = stripcslashes($str);
|
||||
} else {
|
||||
$str = strtr($str, array("\\'" => "'", "\\\\" => "\\"));
|
||||
}
|
||||
return $str;
|
||||
}
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
<?php defined("SYSPATH") or die("No direct script access.");
|
||||
/**
|
||||
* Gallery - a web based photo album viewer and editor
|
||||
* Copyright (C) 2000-2010 Bharat Mediratta
|
||||
*
|
||||
* 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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
class language_block {
|
||||
static function get_site_list() {
|
||||
return array("language" => t("Language preference"));
|
||||
}
|
||||
|
||||
static function get($block_id, $theme) {
|
||||
$block = new Block();
|
||||
if ($block_id == "language") {
|
||||
$locales = locales::installed();
|
||||
if (count($locales) > 1) {
|
||||
foreach ($locales as $locale => $display_name) {
|
||||
$locales[$locale] = SafeString::of_safe_html($display_name);
|
||||
}
|
||||
$block = new Block();
|
||||
$block->css_id = "g-user-language-block";
|
||||
$block->title = t("Language preference");
|
||||
$block->content = new View("user_languages_block.html");
|
||||
$block->content->installed_locales = array_merge(array("" => t("« none »")), $locales);
|
||||
$block->content->selected = (string) locales::cookie_locale();
|
||||
} else {
|
||||
$block = "";
|
||||
}
|
||||
}
|
||||
return $block;
|
||||
}
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
<?php defined("SYSPATH") or die("No direct script access.");
|
||||
/**
|
||||
* Gallery - a web based photo album viewer and editor
|
||||
* Copyright (C) 2000-2010 Bharat Mediratta
|
||||
*
|
||||
* 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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
class language_event_Core {
|
||||
static function admin_menu($menu, $theme) {
|
||||
$menu->get("settings_menu")
|
||||
->append(Menu::factory("link")
|
||||
->id("languages")
|
||||
->label(t("Languages"))
|
||||
->url(url::site("admin/languages")));
|
||||
return $menu;
|
||||
}
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
<?php defined("SYSPATH") or die("No direct script access.");/**
|
||||
* Gallery - a web based photo album viewer and editor
|
||||
* Copyright (C) 2000-2010 Bharat Mediratta
|
||||
*
|
||||
* 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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
class language_installer {
|
||||
static function activate() {
|
||||
module::set_var("gallery", "language_driver", "multi");
|
||||
}
|
||||
|
||||
static function deactivate() {
|
||||
module::set_var("gallery", "language_driver", "basic");
|
||||
module::set_var("gallery", "installed_locales", "en_US");
|
||||
}
|
||||
}
|
@ -1,141 +0,0 @@
|
||||
<?php defined("SYSPATH") or die("No direct script access.");
|
||||
/**
|
||||
* Gallery - a web based photo album viewer and editor
|
||||
* Copyright (C) 2000-2010 Bharat Mediratta
|
||||
*
|
||||
* 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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
class gallery_task_Core {
|
||||
const MPTT_LEFT = 0;
|
||||
const MPTT_RIGHT = 1;
|
||||
|
||||
static function available_tasks() {
|
||||
$tasks = array();
|
||||
$tasks[] = Task_Definition::factory()
|
||||
->callback("gallery_task::update_l10n")
|
||||
->name(t("Update translations"))
|
||||
->description(t("Download new and updated translated strings"))
|
||||
->severity(log::SUCCESS);
|
||||
|
||||
return $tasks;
|
||||
}
|
||||
|
||||
static function update_l10n($task) {
|
||||
$errors = array();
|
||||
try {
|
||||
$start = microtime(true);
|
||||
$data = Cache::instance()->get("update_l10n_cache:{$task->id}");
|
||||
if ($data) {
|
||||
list($dirs, $files, $cache, $num_fetched) = unserialize($data);
|
||||
}
|
||||
$i = 0;
|
||||
|
||||
switch ($task->get("mode", "init")) {
|
||||
case "init": // 0%
|
||||
$dirs = array("gallery", "modules", "themes", "installer");
|
||||
$files = $cache = array();
|
||||
$num_fetched = 0;
|
||||
$task->set("mode", "find_files");
|
||||
$task->status = t("Finding files");
|
||||
break;
|
||||
|
||||
case "find_files": // 0% - 10%
|
||||
while (($dir = array_pop($dirs)) && microtime(true) - $start < 0.5) {
|
||||
if (in_array(basename($dir), array("tests", "lib"))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (glob(DOCROOT . "$dir/*") as $path) {
|
||||
$relative_path = str_replace(DOCROOT, "", $path);
|
||||
if (is_dir($path)) {
|
||||
$dirs[] = $relative_path;
|
||||
} else {
|
||||
$files[] = $relative_path;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$task->status = t2("Finding files: found 1 file",
|
||||
"Finding files: found %count files", count($files));
|
||||
|
||||
if (!$dirs) {
|
||||
$task->set("mode", "scan_files");
|
||||
$task->set("total_files", count($files));
|
||||
$task->status = t("Scanning files");
|
||||
$task->percent_complete = 10;
|
||||
}
|
||||
break;
|
||||
|
||||
case "scan_files": // 10% - 70%
|
||||
while (($file = array_pop($files)) && microtime(true) - $start < 0.5) {
|
||||
$file = DOCROOT . $file;
|
||||
switch (pathinfo($file, PATHINFO_EXTENSION)) {
|
||||
case "php":
|
||||
l10n_scanner::scan_php_file($file, $cache);
|
||||
break;
|
||||
|
||||
case "info":
|
||||
l10n_scanner::scan_info_file($file, $cache);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$total_files = $task->get("total_files");
|
||||
$task->status = t2("Scanning files: scanned 1 file",
|
||||
"Scanning files: scanned %count files", $total_files - count($files));
|
||||
|
||||
$task->percent_complete = 10 + 60 * ($total_files - count($files)) / $total_files;
|
||||
if (empty($files)) {
|
||||
$task->set("mode", "fetch_updates");
|
||||
$task->status = t("Fetching updates");
|
||||
$task->percent_complete = 70;
|
||||
}
|
||||
break;
|
||||
|
||||
case "fetch_updates": // 70% - 100%
|
||||
// Send fetch requests in batches until we're done
|
||||
$num_remaining = l10n_client::fetch_updates($num_fetched);
|
||||
if ($num_remaining) {
|
||||
$total = $num_fetched + $num_remaining;
|
||||
$task->percent_complete = 70 + 30 * ((float) $num_fetched / $total);
|
||||
} else {
|
||||
Gallery_I18n::clear_cache();
|
||||
|
||||
$task->done = true;
|
||||
$task->state = "success";
|
||||
$task->status = t("Translations installed/updated");
|
||||
$task->percent_complete = 100;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$task->done) {
|
||||
Cache::instance()->set("update_l10n_cache:{$task->id}",
|
||||
serialize(array($dirs, $files, $cache, $num_fetched)));
|
||||
} else {
|
||||
Cache::instance()->delete("update_l10n_cache:{$task->id}");
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
Kohana_Log::add("error",(string)$e);
|
||||
$task->done = true;
|
||||
$task->state = "error";
|
||||
$task->status = $e->getMessage();
|
||||
$errors[] = (string)$e;
|
||||
}
|
||||
if ($errors) {
|
||||
$task->log($errors);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,64 +0,0 @@
|
||||
<?php defined("SYSPATH") or die("No direct script access.");/**
|
||||
* Gallery - a web based photo album viewer and editor
|
||||
* Copyright (C) 2000-2010 Bharat Mediratta
|
||||
*
|
||||
* 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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
class language_theme {
|
||||
static function head($theme) {
|
||||
$session = Session::instance();
|
||||
if (count(locales::installed())) {
|
||||
// Needed by the languages block
|
||||
$theme->script("jquery.cookie.js");
|
||||
}
|
||||
|
||||
if ($session->get("l10n_mode", false)) {
|
||||
$theme->css("l10n_client.css");
|
||||
$theme->script("jquery.cookie.js");
|
||||
$theme->script("l10n_client.js");
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
static function admin_head($theme) {
|
||||
$session = Session::instance();
|
||||
if ($session->get("l10n_mode", false)) {
|
||||
$theme->css("l10n_client.css");
|
||||
$theme->script("jquery.cookie.js");
|
||||
$theme->script("l10n_client.js");
|
||||
}
|
||||
}
|
||||
|
||||
static function page_bottom($theme) {
|
||||
$session = Session::instance();
|
||||
if ($session->get("l10n_mode", false)) {
|
||||
return L10n_Client_Controller::l10n_form();
|
||||
}
|
||||
}
|
||||
|
||||
static function admin_page_bottom($theme) {
|
||||
$session = Session::instance();
|
||||
if ($session->get("l10n_mode", false)) {
|
||||
return L10n_Client_Controller::l10n_form();
|
||||
}
|
||||
}
|
||||
|
||||
static function body_attributes() {
|
||||
if (locales::is_rtl()) {
|
||||
return 'class="rtl"';
|
||||
}
|
||||
}
|
||||
}
|
@ -1,315 +0,0 @@
|
||||
// Fork from Drupal's l10n_client module, originally written by:
|
||||
// Gbor Hojtsy http://drupal.org/user/4166 (original author)
|
||||
// Young Hahn / Development Seed - http://developmentseed.org/ (friendly user interface)
|
||||
|
||||
var Gallery = Gallery || { 'behaviors': {} };
|
||||
|
||||
Gallery.attachBehaviors = function(context) {
|
||||
context = context || document;
|
||||
// Execute all of them.
|
||||
jQuery.each(Gallery.behaviors,
|
||||
function() {
|
||||
this(context);
|
||||
});
|
||||
};
|
||||
|
||||
$(document).ready(function() {
|
||||
Gallery.attachBehaviors(this);
|
||||
});
|
||||
|
||||
// Store all l10n_client related data + methods in its own object
|
||||
jQuery.extend(Gallery, {
|
||||
l10nClient: new (function() {
|
||||
// Set "selected" string to unselected, i.e. -1
|
||||
this.selected = -1;
|
||||
// Keybindings
|
||||
this.keys = {'toggle':'ctrl+shift+s', 'clear': 'esc'}; // Keybindings
|
||||
// Keybinding functions
|
||||
this.key = function(pressed) {
|
||||
switch(pressed) {
|
||||
case 'toggle':
|
||||
// Grab user-hilighted text & send it into the search filter
|
||||
userSelection = window.getSelection ? window.getSelection() : document.getSelection ? document.getSelection() : document.selection.createRange().text;
|
||||
userSelection = String(userSelection);
|
||||
if(userSelection.length > 0) {
|
||||
Gallery.l10nClient.filter(userSelection);
|
||||
Gallery.l10nClient.toggle(1);
|
||||
$('#l10n-client #g-l10n-search').focus();
|
||||
} else {
|
||||
if($('#l10n-client').is('.hidden')) {
|
||||
Gallery.l10nClient.toggle(1);
|
||||
if(!$.browser.safari) {
|
||||
$('#l10n-client #g-l10n-search').focus();
|
||||
}
|
||||
} else {
|
||||
Gallery.l10nClient.toggle(0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'clear':
|
||||
this.filter(false);
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
// Toggle the l10nclient
|
||||
this.toggle = function(state) {
|
||||
switch(state) {
|
||||
case 1:
|
||||
$('#l10n-client-string-select, #l10n-client-string-editor, #l10n-client .labels .label').show();
|
||||
$('#l10n-client').height('22em').removeClass('hidden');
|
||||
//$('#l10n-client').slideUp();
|
||||
$('#g-minimize-l10n').text("_");
|
||||
/*
|
||||
* This CSS clashes with Gallery's CSS, probably due to
|
||||
* YUI's grid / floats.
|
||||
if(!$.browser.msie) {
|
||||
$('body').css('border-bottom', '22em solid #fff');
|
||||
}
|
||||
*/
|
||||
$.cookie('Gallery_l10n_client', '1', {expires: 7, path: '/'});
|
||||
break;
|
||||
case 0:
|
||||
$('#l10n-client-string-select, #l10n-client-string-editor, #l10n-client .labels .label').hide();
|
||||
$('#l10n-client').height('2em').addClass('hidden');
|
||||
// TODO: Localize this message
|
||||
$('#g-minimize-l10n').text(MSG_TRANSLATE_TEXT);
|
||||
/*
|
||||
if(!$.browser.msie) {
|
||||
$('body').css('border-bottom', '0px');
|
||||
}
|
||||
*/
|
||||
$.cookie('Gallery_l10n_client', '0', {expires: 7, path: '/'});
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
// Get a string from the DOM tree
|
||||
this.getString = function(index, type) {
|
||||
if (index < l10n_client_data.length) {
|
||||
return l10n_client_data[index][type];
|
||||
}
|
||||
return "";
|
||||
};
|
||||
|
||||
// Set a string in the DOM tree
|
||||
this.setString = function(index, data) {
|
||||
l10n_client_data[index]['translation'] = data;
|
||||
};
|
||||
|
||||
// Display the source message
|
||||
this.showSourceMessage = function(source, is_plural) {
|
||||
if (is_plural) {
|
||||
var pretty_source = $('#source-text-tmp-space').text('[one] - ' + source['one']).html();
|
||||
pretty_source += '<br/>';
|
||||
pretty_source += $('#source-text-tmp-space').text('[other] - ' + source['other']).html();
|
||||
} else {
|
||||
var pretty_source = $('#source-text-tmp-space').text(source).html();
|
||||
}
|
||||
$('#l10n-client-string-editor .source-text').html(pretty_source);
|
||||
};
|
||||
this.isPluralMessage = function(message) {
|
||||
return typeof(message) == 'object';
|
||||
};
|
||||
|
||||
this.updateTranslationForm = function(translation, is_plural) {
|
||||
$('.translationField').addClass('hidden');
|
||||
if (is_plural) {
|
||||
if (typeof(translation) != 'object') {
|
||||
translation = {};
|
||||
}
|
||||
var num_plural_forms = plural_forms.length;
|
||||
for (var i = 0; i < num_plural_forms; i++) {
|
||||
var form = plural_forms[i];
|
||||
if (translation[form] == undefined) {
|
||||
translation[form] = '';
|
||||
}
|
||||
$("#plural-" + form + " textarea[name='l10n-edit-plural-translation-" + form + "']")
|
||||
.attr('value', translation[form]);
|
||||
$('#plural-' + form).removeClass('hidden');
|
||||
}
|
||||
} else {
|
||||
$('#l10n-edit-translation').attr('value', translation);
|
||||
$('#l10n-edit-translation').removeClass('hidden');
|
||||
}
|
||||
};
|
||||
|
||||
// Filter the string list by a search string
|
||||
this.filter = function(search) {
|
||||
if(search == false || search == '') {
|
||||
$('#l10n-client #l10n-search-filter-clear').focus();
|
||||
$('#l10n-client-string-select li').show();
|
||||
$('#l10n-client #g-l10n-search').val('');
|
||||
$('#l10n-client #g-l10n-search').focus();
|
||||
} else {
|
||||
if(search.length > 0) {
|
||||
$('#l10n-client-string-select li').hide();
|
||||
$('#l10n-client-string-select li:contains('+search+')').show();
|
||||
$('#l10n-client #g-l10n-search').val(search);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.copySourceText = function() {
|
||||
var index = Gallery.l10nClient.selected;
|
||||
if (index >= 0) {
|
||||
var source = Gallery.l10nClient.getString(index, 'source');
|
||||
var is_plural = Gallery.l10nClient.isPluralMessage(source);
|
||||
if (is_plural) {
|
||||
if (typeof(translation) != 'object') {
|
||||
translation = {};
|
||||
}
|
||||
var num_plural_forms = plural_forms.length;
|
||||
for (var i = 0; i < num_plural_forms; i++) {
|
||||
var form = plural_forms[i];
|
||||
var text = source['other'];
|
||||
if (form == 'one') {
|
||||
text = source['one'];
|
||||
}
|
||||
$("#plural-" + form + " textarea[name='l10n-edit-plural-translation-" + form + "']")
|
||||
.attr('value', text);
|
||||
}
|
||||
} else {
|
||||
$('#l10n-edit-translation').attr('value', source);
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
})
|
||||
});
|
||||
|
||||
// Attaches the localization editor behavior to all required fields.
|
||||
Gallery.behaviors.l10nClient = function(context) {
|
||||
|
||||
switch($.cookie('Gallery_l10n_client')) {
|
||||
case '1':
|
||||
Gallery.l10nClient.toggle(1);
|
||||
break;
|
||||
default:
|
||||
Gallery.l10nClient.toggle(0);
|
||||
break;
|
||||
}
|
||||
|
||||
// If the selection changes, copy string values to the source and target fields.
|
||||
// Add class to indicate selected string in list widget.
|
||||
$('#l10n-client-string-select li').click(function() {
|
||||
$('#l10n-client-string-select li').removeClass('active');
|
||||
$(this).addClass('active');
|
||||
var index = $('#l10n-client-string-select li').index(this);
|
||||
var source = Gallery.l10nClient.getString(index, 'source');
|
||||
var key = Gallery.l10nClient.getString(index, 'key');
|
||||
var is_plural = Gallery.l10nClient.isPluralMessage(source);
|
||||
Gallery.l10nClient.showSourceMessage(source, is_plural);
|
||||
Gallery.l10nClient.updateTranslationForm(Gallery.l10nClient.getString(index, 'translation'), is_plural);
|
||||
$("#g-l10n-client-save-form input[name='l10n-message-key']").val(key);
|
||||
Gallery.l10nClient.selected = index;
|
||||
});
|
||||
|
||||
// When l10n_client window is clicked, toggle based on current state.
|
||||
$('#g-minimize-l10n').click(function() {
|
||||
if($('#l10n-client').is('.hidden')) {
|
||||
Gallery.l10nClient.toggle(1);
|
||||
} else {
|
||||
Gallery.l10nClient.toggle(0);
|
||||
}
|
||||
});
|
||||
|
||||
// Close the l10n client using an AJAX call and refreshing the page
|
||||
$('#g-close-l10n').click(function(event) {
|
||||
$.ajax({
|
||||
type: "GET",
|
||||
url: toggle_l10n_mode_url,
|
||||
data: "csrf=" + csrf,
|
||||
success: function() {
|
||||
window.location.reload(true);
|
||||
}
|
||||
});
|
||||
event.preventDefault();
|
||||
});
|
||||
|
||||
// Register keybindings using jQuery hotkeys
|
||||
// TODO: Either remove hotkeys code or add query.hotkeys.js.
|
||||
if($.hotkeys) {
|
||||
$.hotkeys.add(Gallery.l10nClient.keys['toggle'], function(){Gallery.l10nClient.key('toggle');});
|
||||
$.hotkeys.add(Gallery.l10nClient.keys['clear'], {target:'#l10n-client #g-l10n-search', type:'keyup'}, function(){Gallery.l10nClient.key('clear');});
|
||||
}
|
||||
|
||||
// never actually submit the form as the search is done in the browser
|
||||
$('#g-l10n-search-form').submit(function() {
|
||||
return false;
|
||||
});
|
||||
|
||||
// Custom listener for l10n_client livesearch
|
||||
$('#l10n-client #g-l10n-search').keyup(function(key) {
|
||||
Gallery.l10nClient.filter($('#l10n-client #g-l10n-search').val());
|
||||
});
|
||||
|
||||
// Clear search
|
||||
$('#l10n-client #l10n-search-filter-clear').click(function() {
|
||||
Gallery.l10nClient.filter(false);
|
||||
return false;
|
||||
});
|
||||
|
||||
// Send AJAX POST data on form submit.
|
||||
$('#g-l10n-client-save-form').ajaxForm({
|
||||
dataType: "json",
|
||||
success: function(data) {
|
||||
var source = Gallery.l10nClient.getString(Gallery.l10nClient.selected, 'source');
|
||||
var is_plural = Gallery.l10nClient.isPluralMessage(source);
|
||||
var num_plural_forms = plural_forms.length;
|
||||
|
||||
// Store translation in local js
|
||||
var translation = {};
|
||||
var is_non_empty = false;
|
||||
if (is_plural) {
|
||||
for (var i = 0; i < num_plural_forms; i++) {
|
||||
var form = plural_forms[i];
|
||||
translation[form] = $("#plural-" + form + " textarea[name='l10n-edit-plural-translation-" + form + "']").attr('value');
|
||||
is_non_empty = is_non_empty || translation[form];
|
||||
}
|
||||
} else {
|
||||
translation = $('#l10n-edit-translation').attr('value');
|
||||
is_non_empty = translation;
|
||||
}
|
||||
Gallery.l10nClient.setString(Gallery.l10nClient.selected, translation);
|
||||
|
||||
// Mark message as translated / untranslated.
|
||||
var source_element = $('#l10n-client-string-select li').eq(Gallery.l10nClient.selected);
|
||||
if (is_non_empty) {
|
||||
source_element.removeClass('untranslated').removeClass('active').addClass('translated');
|
||||
} else {
|
||||
source_element.removeClass('active').removeClass('translated').addClass('untranslated');
|
||||
}
|
||||
|
||||
// Clear the translation form fields
|
||||
Gallery.l10nClient.showSourceMessage('', false);
|
||||
$('#g-l10n-client-save-form #l10n-edit-translation').val('');
|
||||
|
||||
for (var i = 0; i < num_plural_forms; i++) {
|
||||
var form = plural_forms[i];
|
||||
$("#plural-" + form + " textarea[name='l10n-edit-plural-translation-" + form + "']").val('');
|
||||
}
|
||||
$("#g-l10n-client-save-form input[name='l10n-message-key']").val('');
|
||||
},
|
||||
error: function(xmlhttp) {
|
||||
// TODO: Localize this message
|
||||
alert('An HTTP error @status occured (or empty response).'.replace('@status', xmlhttp.status));
|
||||
}
|
||||
});
|
||||
|
||||
// TODO: Add copy/clear buttons (without ajax behavior)
|
||||
/* <input type="submit" name="l10n-edit-copy" value="<?= t("Copy source") ?>"/>
|
||||
<input type="submit" name="l10n-edit-clear" value="<?= t("Clear") ?>"/>
|
||||
*/
|
||||
// TODO: Handle plurals in copy button
|
||||
|
||||
// Copy source text to translation field on button click.
|
||||
$('#g-l10n-client-save-form #l10n-edit-copy').click(function() {
|
||||
$('#g-l10n-client-save-form #l10n-edit-target').val($('#l10n-client-string-editor .source-text').text());
|
||||
});
|
||||
|
||||
// Clear translation field on button click.
|
||||
$('#g-l10n-client-save-form #l10n-edit-clear').click(function() {
|
||||
$('#g-l10n-client-save-form #l10n-edit-target').val('');
|
||||
});
|
||||
};
|
@ -1,553 +0,0 @@
|
||||
<?php defined("SYSPATH") or die("No direct script access.");
|
||||
/**
|
||||
* Gallery - a web based photo album viewer and editor
|
||||
* Copyright (C) 2000-2010 Bharat Mediratta
|
||||
*
|
||||
* 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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Provides a driver-based interface for internationaization and localization.
|
||||
*/
|
||||
class Language_Multi_Driver extends Language_Driver {
|
||||
public function locale($locale=null) {
|
||||
if ($locale) {
|
||||
$this->_config['default_locale'] = $locale;
|
||||
$php_locale = setlocale(LC_ALL, 0);
|
||||
list ($php_locale, $unused) = explode('.', $php_locale . '.');
|
||||
if ($php_locale != $locale) {
|
||||
// Attempt to set PHP's locale as well (for number formatting, collation, etc.)
|
||||
$locale_prefs = array($locale);
|
||||
// Try appending some character set names; some systems (like FreeBSD) need this.
|
||||
// Some systems require a format with hyphen (eg. Gentoo) and others without (eg. FreeBSD).
|
||||
$charsets = array('utf8', 'UTF-8', 'UTF8', 'ISO8859-1', 'ISO-8859-1');
|
||||
if (substr($locale, 0, 2) != 'en') {
|
||||
$charsets = array_merge($charsets, array(
|
||||
'EUC', 'Big5', 'euc', 'ISO8859-2', 'ISO8859-5', 'ISO8859-7',
|
||||
'ISO8859-9', 'ISO-8859-2', 'ISO-8859-5', 'ISO-8859-7', 'ISO-8859-9'));
|
||||
}
|
||||
foreach ($charsets as $charset) {
|
||||
$locale_prefs[] = $locale . '.' . $charset;
|
||||
}
|
||||
$locale_prefs[] = 'en_US';
|
||||
$php_locale = setlocale(LC_ALL, $locale_prefs);
|
||||
}
|
||||
if (is_string($php_locale) && substr($php_locale, 0, 2) == 'tr') {
|
||||
// Make PHP 5 work with Turkish (the localization results are mixed though).
|
||||
// Hack for http://bugs.php.net/18556
|
||||
setlocale(LC_CTYPE, 'C');
|
||||
}
|
||||
}
|
||||
return $this->_config['default_locale'];
|
||||
}
|
||||
|
||||
public function is_rtl($locale=null) {
|
||||
$is_rtl = !empty($this->_config["force_rtl"]);
|
||||
if (empty($is_rtl)) {
|
||||
$locale or $locale = $this->locale();
|
||||
list ($language, $territory) = explode('_', $locale . "_");
|
||||
$is_rtl = in_array($language, array("he", "fa", "ar"));
|
||||
}
|
||||
return $is_rtl;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Language_Driver::translate
|
||||
*/
|
||||
public function translate($message, $options=array()) {
|
||||
$locale = empty($options['locale']) ? $this->_config['default_locale'] : $options['locale'];
|
||||
$count = isset($options['count']) ? $options['count'] : null;
|
||||
$values = $options;
|
||||
unset($values['locale']);
|
||||
$this->log($message, $options);
|
||||
|
||||
$entry = $this->lookup($locale, $message);
|
||||
|
||||
if (null === $entry) {
|
||||
// Default to the root locale.
|
||||
$entry = $message;
|
||||
$locale = $this->_config['root_locale'];
|
||||
}
|
||||
|
||||
$entry = $this->pluralize($locale, $entry, $count);
|
||||
|
||||
$entry = $this->interpolate($locale, $entry, $values);
|
||||
|
||||
return SafeString::of_safe_html($entry);
|
||||
}
|
||||
|
||||
public function has_translation($message, $options=null) {
|
||||
$locale = empty($options['locale']) ? $this->_config['default_locale'] : $options['locale'];
|
||||
|
||||
$entry = $this->lookup($locale, $message);
|
||||
|
||||
if (null === $entry) {
|
||||
return false;
|
||||
} else if (!is_array($message)) {
|
||||
return $entry !== '';
|
||||
} else {
|
||||
if (!is_array($entry) || empty($entry)) {
|
||||
return false;
|
||||
}
|
||||
// It would be better to verify that all the locale's plural forms have a non-empty
|
||||
// translation, but this is fine for now.
|
||||
foreach ($entry as $value) {
|
||||
if ($value === '') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private function lookup($locale, $message) {
|
||||
if (!isset($this->_cache[$locale])) {
|
||||
$this->_cache[$locale] = $this->_load_translations($locale);
|
||||
}
|
||||
|
||||
$key = $this->get_message_key($message);
|
||||
|
||||
if (isset($this->_cache[$locale][$key])) {
|
||||
return $this->_cache[$locale][$key];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private function _load_translations($locale) {
|
||||
$cache_key = "translation|" . $locale;
|
||||
$cache = Cache::instance();
|
||||
$translations = $cache->get($cache_key);
|
||||
if (!isset($translations) || !is_array($translations)) {
|
||||
$translations = array();
|
||||
foreach (db::build()
|
||||
->select("key", "translation")
|
||||
->from("incoming_translations")
|
||||
->where("locale", "=", $locale)
|
||||
->execute() as $row) {
|
||||
$translations[$row->key] = unserialize($row->translation);
|
||||
}
|
||||
|
||||
// Override incoming with outgoing...
|
||||
foreach (db::build()
|
||||
->select("key", "translation")
|
||||
->from("outgoing_translations")
|
||||
->where("locale", "=", $locale)
|
||||
->execute() as $row) {
|
||||
$translations[$row->key] = unserialize($row->translation);
|
||||
}
|
||||
|
||||
$cache->set($cache_key, $translations, array("translation"), 0);
|
||||
}
|
||||
return $translations;
|
||||
}
|
||||
|
||||
protected function _get_plural_key($locale, $count) {
|
||||
$parts = explode('_', $locale);
|
||||
$language = $parts[0];
|
||||
|
||||
// Data from CLDR 1.6 (http://unicode.org/cldr/data/common/supplemental/plurals.xml).
|
||||
// Docs: http://www.unicode.org/cldr/data/charts/supplemental/language_plural_rules.html
|
||||
switch ($language) {
|
||||
case 'az':
|
||||
case 'fa':
|
||||
case 'hu':
|
||||
case 'ja':
|
||||
case 'ko':
|
||||
case 'my':
|
||||
case 'to':
|
||||
case 'tr':
|
||||
case 'vi':
|
||||
case 'yo':
|
||||
case 'zh':
|
||||
case 'bo':
|
||||
case 'dz':
|
||||
case 'id':
|
||||
case 'jv':
|
||||
case 'ka':
|
||||
case 'km':
|
||||
case 'kn':
|
||||
case 'ms':
|
||||
case 'th':
|
||||
return 'other';
|
||||
|
||||
case 'ar':
|
||||
if ($count == 0) {
|
||||
return 'zero';
|
||||
} else if ($count == 1) {
|
||||
return 'one';
|
||||
} else if ($count == 2) {
|
||||
return 'two';
|
||||
} else if (is_int($count) && ($i = $count % 100) >= 3 && $i <= 10) {
|
||||
return 'few';
|
||||
} else if (is_int($count) && ($i = $count % 100) >= 11 && $i <= 99) {
|
||||
return 'many';
|
||||
} else {
|
||||
return 'other';
|
||||
}
|
||||
|
||||
case 'pt':
|
||||
case 'am':
|
||||
case 'bh':
|
||||
case 'fil':
|
||||
case 'tl':
|
||||
case 'guw':
|
||||
case 'hi':
|
||||
case 'ln':
|
||||
case 'mg':
|
||||
case 'nso':
|
||||
case 'ti':
|
||||
case 'wa':
|
||||
if ($count == 0 || $count == 1) {
|
||||
return 'one';
|
||||
} else {
|
||||
return 'other';
|
||||
}
|
||||
|
||||
case 'fr':
|
||||
if ($count >= 0 and $count < 2) {
|
||||
return 'one';
|
||||
} else {
|
||||
return 'other';
|
||||
}
|
||||
|
||||
case 'lv':
|
||||
if ($count == 0) {
|
||||
return 'zero';
|
||||
} else if ($count % 10 == 1 && $count % 100 != 11) {
|
||||
return 'one';
|
||||
} else {
|
||||
return 'other';
|
||||
}
|
||||
|
||||
case 'ga':
|
||||
case 'se':
|
||||
case 'sma':
|
||||
case 'smi':
|
||||
case 'smj':
|
||||
case 'smn':
|
||||
case 'sms':
|
||||
if ($count == 1) {
|
||||
return 'one';
|
||||
} else if ($count == 2) {
|
||||
return 'two';
|
||||
} else {
|
||||
return 'other';
|
||||
}
|
||||
|
||||
case 'ro':
|
||||
case 'mo':
|
||||
if ($count == 1) {
|
||||
return 'one';
|
||||
} else if (is_int($count) && $count == 0 && ($i = $count % 100) >= 1 && $i <= 19) {
|
||||
return 'few';
|
||||
} else {
|
||||
return 'other';
|
||||
}
|
||||
|
||||
case 'lt':
|
||||
if (is_int($count) && $count % 10 == 1 && $count % 100 != 11) {
|
||||
return 'one';
|
||||
} else if (is_int($count) && ($i = $count % 10) >= 2 && $i <= 9 && ($i = $count % 100) < 11 && $i > 19) {
|
||||
return 'few';
|
||||
} else {
|
||||
return 'other';
|
||||
}
|
||||
|
||||
case 'hr':
|
||||
case 'ru':
|
||||
case 'sr':
|
||||
case 'uk':
|
||||
case 'be':
|
||||
case 'bs':
|
||||
case 'sh':
|
||||
if (is_int($count) && $count % 10 == 1 && $count % 100 != 11) {
|
||||
return 'one';
|
||||
} else if (is_int($count) && ($i = $count % 10) >= 2 && $i <= 4 && ($i = $count % 100) < 12 && $i > 14) {
|
||||
return 'few';
|
||||
} else if (is_int($count) && ($count % 10 == 0 || (($i = $count % 10) >= 5 && $i <= 9) || (($i = $count % 100) >= 11 && $i <= 14))) {
|
||||
return 'many';
|
||||
} else {
|
||||
return 'other';
|
||||
}
|
||||
|
||||
case 'cs':
|
||||
case 'sk':
|
||||
if ($count == 1) {
|
||||
return 'one';
|
||||
} else if (is_int($count) && $count >= 2 && $count <= 4) {
|
||||
return 'few';
|
||||
} else {
|
||||
return 'other';
|
||||
}
|
||||
|
||||
case 'pl':
|
||||
if ($count == 1) {
|
||||
return 'one';
|
||||
} else if (is_int($count) && ($i = $count % 10) >= 2 && $i <= 4 &&
|
||||
($i = $count % 100) < 12 && $i > 14 && ($i = $count % 100) < 22 && $i > 24) {
|
||||
return 'few';
|
||||
} else {
|
||||
return 'other';
|
||||
}
|
||||
|
||||
case 'sl':
|
||||
if ($count % 100 == 1) {
|
||||
return 'one';
|
||||
} else if ($count % 100 == 2) {
|
||||
return 'two';
|
||||
} else if (is_int($count) && ($i = $count % 100) >= 3 && $i <= 4) {
|
||||
return 'few';
|
||||
} else {
|
||||
return 'other';
|
||||
}
|
||||
|
||||
case 'mt':
|
||||
if ($count == 1) {
|
||||
return 'one';
|
||||
} else if ($count == 0 || is_int($count) && ($i = $count % 100) >= 2 && $i <= 10) {
|
||||
return 'few';
|
||||
} else if (is_int($count) && ($i = $count % 100) >= 11 && $i <= 19) {
|
||||
return 'many';
|
||||
} else {
|
||||
return 'other';
|
||||
}
|
||||
|
||||
case 'mk':
|
||||
if ($count % 10 == 1) {
|
||||
return 'one';
|
||||
} else {
|
||||
return 'other';
|
||||
}
|
||||
|
||||
case 'cy':
|
||||
if ($count == 1) {
|
||||
return 'one';
|
||||
} else if ($count == 2) {
|
||||
return 'two';
|
||||
} else if ($count == 8 || $count == 11) {
|
||||
return 'many';
|
||||
} else {
|
||||
return 'other';
|
||||
}
|
||||
|
||||
default: // en, de, etc.
|
||||
return $count == 1 ? 'one' : 'other';
|
||||
}
|
||||
}
|
||||
|
||||
// @todo Might want to add a localizable language name as well.
|
||||
public function initialize_language_data() {
|
||||
$l["af_ZA"] = "Afrikaans"; // Afrikaans
|
||||
$l["ar_SA"] = "العربية"; // Arabic
|
||||
$l["be_BY"] = "Беларускі"; // Belarusian
|
||||
$l["bg_BG"] = "български"; // Bulgarian
|
||||
$l["ca_ES"] = "Catalan"; // Catalan
|
||||
$l["cs_CZ"] = "čeština"; // Czech
|
||||
$l["da_DK"] = "Dansk"; // Danish
|
||||
$l["de_DE"] = "Deutsch"; // German
|
||||
$l["el_GR"] = "Greek"; // Greek
|
||||
$l["en_GB"] = "English (UK)"; // English (UK)
|
||||
$l["en_US"] = "English (US)"; // English (US)
|
||||
$l["es_AR"] = "Español (AR)"; // Spanish (AR)
|
||||
$l["es_ES"] = "Español"; // Spanish (ES)
|
||||
$l["es_MX"] = "Español (MX)"; // Spanish (MX)
|
||||
$l["et_EE"] = "Eesti"; // Estonian
|
||||
$l["eu_ES"] = "Euskara"; // Basque
|
||||
$l["fa_IR"] = "فارس"; // Farsi
|
||||
$l["fi_FI"] = "Suomi"; // Finnish
|
||||
$l["fo_FO"] = "Føroyskt"; // Faroese
|
||||
$l["fr_FR"] = "Français"; // French
|
||||
$l["ga_IE"] = "Gaeilge"; // Irish
|
||||
$l["he_IL"] = "עברית"; // Hebrew
|
||||
$l["hu_HU"] = "Magyar"; // Hungarian
|
||||
$l["is_IS"] = "Icelandic"; // Icelandic
|
||||
$l["it_IT"] = "Italiano"; // Italian
|
||||
$l["ja_JP"] = "日本語"; // Japanese
|
||||
$l["ko_KR"] = "한국어"; // Korean
|
||||
$l["lt_LT"] = "Lietuvių"; // Lithuanian
|
||||
$l["lv_LV"] = "Latviešu"; // Latvian
|
||||
$l["nl_NL"] = "Nederlands"; // Dutch
|
||||
$l["no_NO"] = "Norsk bokmål"; // Norwegian
|
||||
$l["pl_PL"] = "Polski"; // Polish
|
||||
$l["pt_BR"] = "Português do Brasil"; // Portuguese (BR)
|
||||
$l["pt_PT"] = "Português ibérico"; // Portuguese (PT)
|
||||
$l["ro_RO"] = "Română"; // Romanian
|
||||
$l["ru_RU"] = "Русский"; // Russian
|
||||
$l["sk_SK"] = "Slovenčina"; // Slovak
|
||||
$l["sl_SI"] = "Slovenščina"; // Slovenian
|
||||
$l["sr_CS"] = "Srpski"; // Serbian
|
||||
$l["sv_SE"] = "Svenska"; // Swedish
|
||||
$l["tr_TR"] = "Türkçe"; // Turkish
|
||||
$l["uk_UA"] = "українська"; // Ukrainian
|
||||
$l["vi_VN"] = "Tiếng Việt"; // Vietnamese
|
||||
$l["zh_CN"] = "简体中文"; // Chinese (CN)
|
||||
$l["zh_TW"] = "繁體中文"; // Chinese (TW)
|
||||
asort($l, SORT_LOCALE_STRING);
|
||||
|
||||
// Language subtag to (default) locale mapping
|
||||
foreach ($l as $locale => $name) {
|
||||
list ($language) = explode("_", $locale . "_");
|
||||
// The first one mentioned is the default
|
||||
if (!isset($d[$language])) {
|
||||
$d[$language] = $locale;
|
||||
}
|
||||
}
|
||||
|
||||
$this->locales = $l;
|
||||
$this->language_subtag_to_locale = $d;
|
||||
}
|
||||
|
||||
public function set_request_locale() {
|
||||
// 1. Check the session specific preference (cookie)
|
||||
$locale = $this->cookie_locale();
|
||||
// 2. Check the user's preference
|
||||
if (!$locale) {
|
||||
$locale = identity::active_user()->locale;
|
||||
}
|
||||
// 3. Check the browser's / OS' preference
|
||||
if (!$locale) {
|
||||
$locale = $this->_locale_from_http_request();
|
||||
}
|
||||
// If we have any preference, override the site's default locale
|
||||
if ($locale) {
|
||||
$this->locale($locale);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the best match comparing the HTTP accept-language header
|
||||
* with the installed locales.
|
||||
* @todo replace this with request::accepts_language() when we upgrade to Kohana 2.4
|
||||
*/
|
||||
private function _locale_from_http_request() {
|
||||
$http_accept_language = Input::instance()->server("HTTP_ACCEPT_LANGUAGE");
|
||||
if ($http_accept_language) {
|
||||
// Parse the HTTP header and build a preference list
|
||||
// Example value: "de,en-us;q=0.7,en-uk,fr-fr;q=0.2"
|
||||
$locale_preferences = array();
|
||||
foreach (explode(",", $http_accept_language) as $code) {
|
||||
list ($requested_locale, $qvalue) = explode(";", $code . ";");
|
||||
$requested_locale = trim($requested_locale);
|
||||
$qvalue = trim($qvalue);
|
||||
if (preg_match("/^([a-z]{2,3})(?:[_-]([a-zA-Z]{2}))?/", $requested_locale, $matches)) {
|
||||
$requested_locale = strtolower($matches[1]);
|
||||
if (!empty($matches[2])) {
|
||||
$requested_locale .= "_" . strtoupper($matches[2]);
|
||||
}
|
||||
$requested_locale = trim(str_replace("-", "_", $requested_locale));
|
||||
if (!strlen($qvalue)) {
|
||||
// If not specified, default to 1.
|
||||
$qvalue = 1;
|
||||
} else {
|
||||
// qvalue is expected to be something like "q=0.7"
|
||||
list ($ignored, $qvalue) = explode("=", $qvalue . "==");
|
||||
$qvalue = floatval($qvalue);
|
||||
}
|
||||
// Group by language to boost inexact same-language matches
|
||||
list ($language) = explode("_", $requested_locale . "_");
|
||||
if (!isset($locale_preferences[$language])) {
|
||||
$locale_preferences[$language] = array();
|
||||
}
|
||||
$locale_preferences[$language][$requested_locale] = $qvalue;
|
||||
}
|
||||
}
|
||||
|
||||
// Compare and score requested locales with installed ones
|
||||
$scored_locales = array();
|
||||
foreach ($locale_preferences as $language => $requested_locales) {
|
||||
// Inexact match adjustment (same language, different region)
|
||||
$fallback_adjustment_factor = 0.95;
|
||||
if (count($requested_locales) > 1) {
|
||||
// Sort by qvalue, descending
|
||||
$qvalues = array_values($requested_locales);
|
||||
rsort($qvalues);
|
||||
// Ensure inexact match scores worse than 2nd preference in same language.
|
||||
$fallback_adjustment_factor *= $qvalues[1];
|
||||
}
|
||||
foreach ($requested_locales as $requested_locale => $qvalue) {
|
||||
list ($matched_locale, $match_score) =
|
||||
$this->_locale_match_score($requested_locale, $qvalue, $fallback_adjustment_factor);
|
||||
if ($matched_locale &&
|
||||
(!isset($scored_locales[$matched_locale]) ||
|
||||
$match_score > $scored_locales[$matched_locale])) {
|
||||
$scored_locales[$matched_locale] = $match_score;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
arsort($scored_locales);
|
||||
|
||||
list ($locale) = each($scored_locales);
|
||||
return $locale;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private function _locale_match_score($requested_locale, $qvalue, $adjustment_factor) {
|
||||
$installed = $this->installed();
|
||||
if (isset($installed[$requested_locale])) {
|
||||
return array($requested_locale, $qvalue);
|
||||
}
|
||||
list ($language) = explode("_", $requested_locale . "_");
|
||||
if (isset($this->language_subtag_to_locale[$language]) &&
|
||||
isset($installed[$this->language_subtag_to_locale[$language]])) {
|
||||
$score = $adjustment_factor * $qvalue;
|
||||
return array($this->language_subtag_to_locale[$language], $score);
|
||||
}
|
||||
return array(null, 0);
|
||||
}
|
||||
|
||||
public function cookie_locale() {
|
||||
// Can't use Input framework for client side cookies since
|
||||
// they're not signed.
|
||||
$cookie_data = isset($_COOKIE["g_locale"]) ? $_COOKIE["g_locale"] : null;
|
||||
$locale = null;
|
||||
if ($cookie_data) {
|
||||
if (preg_match("/^([a-z]{2,3}(?:_[A-Z]{2})?)$/", trim($cookie_data), $matches)) {
|
||||
$requested_locale = $matches[1];
|
||||
$installed_locales = locales::installed();
|
||||
if (isset($installed_locales[$requested_locale])) {
|
||||
$locale = $requested_locale;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $locale;
|
||||
}
|
||||
|
||||
public function update_installed($locales) {
|
||||
// Ensure that the default is included...
|
||||
$default = module::get_var("gallery", "default_locale");
|
||||
$locales = in_array($default, $locales)
|
||||
? $locales
|
||||
: array_merge($locales, array($default));
|
||||
|
||||
module::set_var("gallery", "installed_locales", join("|", $locales));
|
||||
|
||||
// Clear the cache
|
||||
$this->locales = null;
|
||||
}
|
||||
|
||||
public function display_name($locale=null) {
|
||||
if (empty($this->locales)) {
|
||||
$this->initialize_language_data();
|
||||
}
|
||||
$locale or $locale = Gallery_I18n::instance()->locale();
|
||||
|
||||
return $this->locales[$locale];
|
||||
}
|
||||
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
name = Multi-Language Support
|
||||
description = "Provide support for internationalization (i18n) and localization(i10n)"
|
||||
|
||||
version = 1
|
@ -1,115 +0,0 @@
|
||||
<?php defined("SYSPATH") or die("No direct script access.") ?>
|
||||
<script type="text/javascript">
|
||||
var old_default_locale = <?= html::js_string($default_locale) ?>;
|
||||
|
||||
$("#g-languages-form").ready(function() {
|
||||
$("input[name='installed_locales[]']").change(function (event) {
|
||||
if (this.checked) {
|
||||
$("input[type='radio'][value='" + this.value + "']").enable();
|
||||
} else {
|
||||
if ($("input[type='radio'][value='" + this.value + "']").selected()) { // if you deselect your default language, switch to some other installed language
|
||||
$("input[type='radio'][value='" + old_default_locale + "']").attr("checked", "checked");
|
||||
}
|
||||
$("input[type='radio'][value='" + this.value + "']").attr("disabled", "disabled");
|
||||
}
|
||||
});
|
||||
|
||||
$("#g-languages-form").ajaxForm({
|
||||
dataType: "json",
|
||||
success: function(data) {
|
||||
if (data.result == "success") {
|
||||
el = $('<a href="' + <?= html::js_string(url::site("admin/maintenance/start/gallery_task::update_l10n?csrf=$csrf")) ?> + '"></a>'); // this is a little hack to trigger the update_l10n task in a dialog
|
||||
el.gallery_dialog();
|
||||
el.trigger('click');
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<div class="g-block">
|
||||
<h1> <?= t("Languages and translation") ?> </h1>
|
||||
|
||||
<div class="g-block-content">
|
||||
|
||||
<div id="g-languages" class="g-block">
|
||||
<h2> <?= t("Languages") ?> </h2>
|
||||
<p>
|
||||
<?= t("Install new languages, update installed ones and set the default language for your Gallery.") ?>
|
||||
</p>
|
||||
|
||||
<div class="g-block-content ui-helper-clearfix">
|
||||
<form id="g-languages-form" method="post" action="<?= url::site("admin/languages/save") ?>">
|
||||
<?= access::csrf_form_field() ?>
|
||||
<table class="g-left">
|
||||
<tr>
|
||||
<th> <?= t("Installed") ?> </th>
|
||||
<th> <?= t("Language") ?> </th>
|
||||
<th> <?= t("Default language") ?> </th>
|
||||
</tr>
|
||||
<? $i = 0 ?>
|
||||
<? foreach ($available_locales as $code => $display_name): ?>
|
||||
<? if ($i == (int) (count($available_locales)/2)): ?>
|
||||
</table>
|
||||
<table>
|
||||
<tr>
|
||||
<th> <?= t("Installed") ?> </th>
|
||||
<th> <?= t("Language") ?> </th>
|
||||
<th> <?= t("Default language") ?> </th>
|
||||
</tr>
|
||||
<? endif ?>
|
||||
<tr class="<?= (isset($installed_locales[$code])) ? "g-available" : "" ?><?= ($default_locale == $code) ? " g-selected" : "" ?>">
|
||||
<td> <?= form::checkbox("installed_locales[]", $code, isset($installed_locales[$code])) ?> </td>
|
||||
<td> <?= $display_name ?> </td>
|
||||
<td>
|
||||
<?= form::radio("default_locale", $code, ($default_locale == $code), ((isset($installed_locales[$code]))?'':'disabled="disabled"') ) ?>
|
||||
</td>
|
||||
</tr>
|
||||
<? $i++ ?>
|
||||
<? endforeach ?>
|
||||
</table>
|
||||
<input type="submit" value="<?= t("Update languages")->for_html_attr() ?>" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="g-translations" class="g-block">
|
||||
<h2> <?= t("Translations") ?> </h2>
|
||||
<p>
|
||||
<?= t("Create your own translations and share them with the rest of the Gallery community.") ?>
|
||||
</p>
|
||||
|
||||
<div class="g-block-content">
|
||||
<a href="http://codex.gallery2.org/Gallery3:Localization" target="_blank"
|
||||
class="g-right ui-state-default ui-corner-all ui-icon ui-icon-help"
|
||||
title="<?= t("Localization documentation")->for_html_attr() ?>">
|
||||
<?= t("Localization documentation") ?>
|
||||
</a>
|
||||
|
||||
<h3><?= t("Translating Gallery") ?></h3>
|
||||
|
||||
<p><?= t("Follow these steps to begin translating Gallery.") ?></p>
|
||||
|
||||
<ol>
|
||||
<li><?= t("Make sure the target language is installed and up to date (check above).") ?></li>
|
||||
<li><?= t("Make sure you have selected the right target language (currently %default_locale).",
|
||||
array("default_locale" => locales::display_name())) ?></li>
|
||||
<li><?= t("Start the translation mode and the translation interface will appear at the bottom of each Gallery page.") ?></li>
|
||||
</ol>
|
||||
<a href="<?= url::site("l10n_client/toggle_l10n_mode?csrf=".access::csrf_token()) ?>"
|
||||
class="g-button ui-state-default ui-corner-all ui-icon-left">
|
||||
<span class="ui-icon ui-icon-power"></span>
|
||||
<? if (Session::instance()->get("l10n_mode", false)): ?>
|
||||
<?= t("Stop translation mode") ?>
|
||||
<? else: ?>
|
||||
<?= t("Start translation mode") ?>
|
||||
<? endif ?>
|
||||
</a>
|
||||
|
||||
<h3><?= t("Sharing your translations") ?></h3>
|
||||
<?= $share_translations_form ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
@ -1,82 +0,0 @@
|
||||
<?php defined("SYSPATH") or die("No direct script access.") ?>
|
||||
<div id="l10n-client" class="hidden">
|
||||
<div class="labels">
|
||||
<span id="l10n-client-toggler">
|
||||
<a id="g-minimize-l10n">_</a>
|
||||
<a id="g-close-l10n" title="<?= t("Stop the translation mode")->for_html_attr() ?>"
|
||||
href="<?= html::clean_attribute(url::site("l10n_client/toggle_l10n_mode?csrf=".access::csrf_token())) ?>">X</a>
|
||||
</span>
|
||||
<div class="label strings"><h2><?= t("Page text") ?>
|
||||
<? if (!Input::instance()->get('show_all_l10n_messages')): ?>
|
||||
<a style="background-color:#fff" href="<?= url::site("admin/languages?show_all_l10n_messages=1") ?>"><?= t("(Show all)") ?></a>
|
||||
<? endif; ?>
|
||||
</h2></div>
|
||||
<div class="label source"><h2><?= t("Source") ?></div>
|
||||
<div class="label translation"><h2><?= t("Translation to %language",
|
||||
array("language" => locales::display_name())) ?></h2></div>
|
||||
</div>
|
||||
<div id="l10n-client-string-select">
|
||||
<ul class="string-list">
|
||||
<? foreach ($string_list as $string): ?>
|
||||
<li class="<?= $string["translation"] === "" ? "untranslated" : "translated" ?>">
|
||||
<? if (is_array($string["source"])): ?>
|
||||
[one] - <?= $string["source"]["one"] ?><br/>
|
||||
[other] - <?= $string["source"]["other"] ?>
|
||||
<? else: ?>
|
||||
<?= $string["source"] ?>
|
||||
<? endif; ?>
|
||||
</li>
|
||||
<? endforeach; ?>
|
||||
</ul>
|
||||
|
||||
<?= $l10n_search_form ?>
|
||||
</div>
|
||||
<div id="l10n-client-string-editor">
|
||||
<div class="source">
|
||||
<p class="source-text"></p>
|
||||
<p id="source-text-tmp-space" style="display:none"></p>
|
||||
</div>
|
||||
<div class="translation">
|
||||
<form method="post" action="<?= url::site("l10n_client/save") ?>" id="g-l10n-client-save-form">
|
||||
<?= access::csrf_form_field() ?>
|
||||
<?= form::hidden("l10n-message-key") ?>
|
||||
<?= form::textarea("l10n-edit-translation", "", ' id="l10n-edit-translation" rows="5" class="translationField"') ?>
|
||||
<div id="plural-zero" class="translationField hidden">
|
||||
<label for="l10n-edit-plural-translation-zero">[zero]</label>
|
||||
<?= form::textarea("l10n-edit-plural-translation-zero", "", ' rows="2"') ?>
|
||||
</div>
|
||||
<div id="plural-one" class="translationField hidden">
|
||||
<label for="l10n-edit-plural-translation-one">[one]</label>
|
||||
<?= form::textarea("l10n-edit-plural-translation-one", "", ' rows="2"') ?>
|
||||
</div>
|
||||
<div id="plural-two" class="translationField hidden">
|
||||
<label for="l10n-edit-plural-translation-two">[two]</label>
|
||||
<?= form::textarea("l10n-edit-plural-translation-two", "", ' rows="2"') ?>
|
||||
</div>
|
||||
<div id="plural-few" class="translationField hidden">
|
||||
<label for="l10n-edit-plural-translation-few">[few]</label>
|
||||
<?= form::textarea("l10n-edit-plural-translation-few", "", ' rows="2"') ?>
|
||||
</div>
|
||||
<div id="plural-many" class="translationField hidden">
|
||||
<label for="l10n-edit-plural-translation-many">[many]</label>
|
||||
<?= form::textarea("l10n-edit-plural-translation-many", "", ' rows="2"') ?>
|
||||
</div>
|
||||
<div id="plural-other" class="translationField hidden">
|
||||
<label for="l10n-edit-plural-translation-other">[other]</label>
|
||||
(<a href="http://www.unicode.org/cldr/data/charts/supplemental/language_plural_rules.html"><?= t("learn more about plural forms") ?></a>)
|
||||
<?= form::textarea("l10n-edit-plural-translation-other", "", ' rows="2"') ?>
|
||||
</div>
|
||||
<input type="submit" name="l10n-edit-save" value="<?= t("Save translation")->for_html_attr() ?>"/>
|
||||
<a href="javascript: Gallery.l10nClient.copySourceText()"
|
||||
class="g-button ui-state-default ui-corner-all"><?= t("Copy source text") ?></a>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
var MSG_TRANSLATE_TEXT = <?= t("Translate text")->for_js() ?>;
|
||||
var l10n_client_data = <?= json_encode($string_list) ?>;
|
||||
var plural_forms = <?= json_encode($plural_forms) ?>;
|
||||
var toggle_l10n_mode_url = <?= html::js_string(url::site("l10n_client/toggle_l10n_mode")) ?>;
|
||||
var csrf = <?= html::js_string(access::csrf_token()) ?>;
|
||||
</script>
|
||||
</div>
|
@ -1,19 +0,0 @@
|
||||
<?php defined("SYSPATH") or die("No direct script access.") ?>
|
||||
<?= form::dropdown("g-select-session-locale", $installed_locales, $selected) ?>
|
||||
<script type="text/javascript">
|
||||
$("select[name=g-select-session-locale]").change(function() {
|
||||
var old_locale_preference = <?= html::js_string($selected) ?>;
|
||||
var locale = $(this).val();
|
||||
if (old_locale_preference == locale) {
|
||||
return;
|
||||
}
|
||||
|
||||
var expires = -1;
|
||||
if (locale) {
|
||||
expires = 365;
|
||||
}
|
||||
$.cookie("g_locale", locale, {"expires": expires, "path": "/"});
|
||||
window.location.reload(true);
|
||||
});
|
||||
</script>
|
||||
|
Reference in New Issue
Block a user