public static function l10n_form() { if (Input::instance()->get("show_all_l10n_messages")) { $calls = array(); foreach (Database::instance()->select("key", "message")->from("incoming_translations")->where(array("locale" => 'root'))->get()->as_array() as $row) { $calls[$row->key] = array(unserialize($row->message), array()); } } else { $calls = I18n::instance()->call_log(); } $locale = I18n::instance()->locale(); if ($calls) { $translations = array(); foreach (Database::instance()->select("key", "translation")->from("incoming_translations")->where(array("locale" => $locale))->get()->as_array() as $row) { $translations[$row->key] = unserialize($row->translation); } // Override incoming with outgoing... foreach (Database::instance()->select("key", "translation")->from("outgoing_translations")->where(array("locale" => $locale))->get()->as_array() 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 ''; }
private function _share_translations_form() { $form = new Forge("admin/languages/share", "", "post", array("id" => "gShareTranslationsForm")); $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::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; }
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 * ((double) $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); } }
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? $request = new stdClass(); 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} = new stdClass(); $request->{$key}->translations = new stdClass(); $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("submit"); $signature = self::_sign($request_data); list($response_data, $response_status) = remote::post($url, array("data" => $request_data, "client_token" => l10n_client::client_token(), "signature" => $signature, "uid" => l10n_client::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? }
static function update_l10n(&$task) { $message = array(); try { $start = microtime(true); $dirs = $task->get("dirs"); $files = $task->get("files"); $cache = $task->get("cache", array()); $i = 0; switch ($task->get("mode", "init")) { case "init": // 0% $dirs = array("gallery", "modules", "themes", "installer"); $files = array(); $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; } } } $message[] = $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% - 90% 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"); $message[] = $task->status = t2("Scanning files: scanned 1 file", "Scanning files: scanned %count files", $total_files - count($files)); $task->percent_complete = 10 + 80 * ($total_files - count($files)) / $total_files; if (empty($files)) { $task->set("mode", "fetch_updates"); $task->status = t("Fetching updates"); $task->percent_complete = 90; } break; case "fetch_updates": // 90% - 100% $message = array_merge($message, l10n_client::fetch_updates()); $task->done = true; $task->state = "success"; $task->status = t("Translations installed/updated"); $task->percent_complete = 100; } $task->set("files", $files); $task->set("dirs", $dirs); $task->set("cache", $cache); } catch (Exception $e) { $task->done = true; $task->state = "error"; $task->status = $e->getMessage(); $message[] = $e->__toString(); } $task->log($message); }