parent
6bc831ae19
commit
2bbbfc972c
60 changed files with 6558 additions and 111 deletions
102
imgboard.php
102
imgboard.php
|
@ -25,6 +25,8 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
use Gettext\Translator;
|
||||
use Gettext\Translations;
|
||||
|
||||
error_reporting(E_ALL);
|
||||
ini_set("display_errors", 1);
|
||||
|
@ -60,24 +62,24 @@ if (!file_exists('settings.php')) {
|
|||
}
|
||||
require 'settings.php';
|
||||
|
||||
if (function_exists('_')) {
|
||||
if (defined('TINYIB_LOCALE')) {
|
||||
setlocale(LC_ALL, TINYIB_LOCALE);
|
||||
}
|
||||
bindtextdomain('tinyib', 'locale');
|
||||
textdomain('tinyib');
|
||||
} else {
|
||||
function _($string) {
|
||||
if (TINYIB_LOCALE == '') {
|
||||
function __($string) {
|
||||
return $string;
|
||||
}
|
||||
} else {
|
||||
require 'inc/gettext/src/autoloader.php';
|
||||
$translations = Translations::fromPoFile('locale/' . TINYIB_LOCALE . '/LC_MESSAGES/tinyib.po');
|
||||
$translator = new Translator();
|
||||
$translator->loadTranslations($translations);
|
||||
$translator->register();
|
||||
}
|
||||
|
||||
if (TINYIB_TRIPSEED == '' || TINYIB_ADMINPASS == '') {
|
||||
fancyDie(_('TINYIB_TRIPSEED and TINYIB_ADMINPASS must be configured.'));
|
||||
fancyDie(__('TINYIB_TRIPSEED and TINYIB_ADMINPASS must be configured.'));
|
||||
}
|
||||
|
||||
if (TINYIB_CAPTCHA === 'recaptcha' && (TINYIB_RECAPTCHA_SITE == '' || TINYIB_RECAPTCHA_SECRET == '')) {
|
||||
fancyDie(_('TINYIB_RECAPTCHA_SITE and TINYIB_RECAPTCHA_SECRET must be configured.'));
|
||||
fancyDie(__('TINYIB_RECAPTCHA_SITE and TINYIB_RECAPTCHA_SECRET must be configured.'));
|
||||
}
|
||||
|
||||
// Check directories are writable by the script
|
||||
|
@ -87,7 +89,7 @@ if (TINYIB_DBMODE == 'flatfile') {
|
|||
}
|
||||
foreach ($writedirs as $dir) {
|
||||
if (!is_writable($dir)) {
|
||||
fancyDie(sprintf(_("Directory '%s' can not be written to. Please modify its permissions."), $dir));
|
||||
fancyDie(sprintf(__("Directory '%s' can not be written to. Please modify its permissions."), $dir));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -95,7 +97,7 @@ $includes = array("inc/defines.php", "inc/functions.php", "inc/html.php");
|
|||
if (in_array(TINYIB_DBMODE, array('flatfile', 'mysql', 'mysqli', 'sqlite', 'sqlite3', 'pdo'))) {
|
||||
$includes[] = 'inc/database_' . TINYIB_DBMODE . '.php';
|
||||
} else {
|
||||
fancyDie(_('Unknown database mode specified.'));
|
||||
fancyDie(__('Unknown database mode specified.'));
|
||||
}
|
||||
|
||||
foreach ($includes as $include) {
|
||||
|
@ -110,7 +112,7 @@ $redirect = true;
|
|||
// Check if the request is to make a post
|
||||
if (!isset($_GET['delete']) && !isset($_GET['manage']) && (isset($_POST['name']) || isset($_POST['email']) || isset($_POST['subject']) || isset($_POST['message']) || isset($_POST['file']) || isset($_POST['embed']) || isset($_POST['password']))) {
|
||||
if (TINYIB_DBMIGRATE) {
|
||||
fancyDie(_('Posting is currently disabled.<br>Please try again in a few moments.'));
|
||||
fancyDie(__('Posting is currently disabled.<br>Please try again in a few moments.'));
|
||||
}
|
||||
|
||||
list($loggedin, $isadmin) = manageCheckLogIn();
|
||||
|
@ -129,9 +131,9 @@ if (!isset($_GET['delete']) && !isset($_GET['manage']) && (isset($_POST['name'])
|
|||
if ($post['parent'] != TINYIB_NEWTHREAD && !$loggedin) {
|
||||
$parent = postByID($post['parent']);
|
||||
if (!isset($parent['locked'])) {
|
||||
fancyDie(_('Invalid parent thread ID supplied, unable to create post.'));
|
||||
fancyDie(__('Invalid parent thread ID supplied, unable to create post.'));
|
||||
} else if ($parent['locked'] == 1) {
|
||||
fancyDie(_('Replies are not allowed to locked threads.'));
|
||||
fancyDie(__('Replies are not allowed to locked threads.'));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -168,12 +170,12 @@ if (!isset($_GET['delete']) && !isset($_GET['manage']) && (isset($_POST['name'])
|
|||
|
||||
if (isset($_POST['embed']) && trim($_POST['embed']) != '' && ($rawpost || !in_array('embed', $hide_fields))) {
|
||||
if (isset($_FILES['file']) && $_FILES['file']['name'] != "") {
|
||||
fancyDie(_('Embedding a URL and uploading a file at the same time is not supported.'));
|
||||
fancyDie(__('Embedding a URL and uploading a file at the same time is not supported.'));
|
||||
}
|
||||
|
||||
list($service, $embed) = getEmbed(trim($_POST['embed']));
|
||||
if (empty($embed) || !isset($embed['html']) || !isset($embed['title']) || !isset($embed['thumbnail_url'])) {
|
||||
fancyDie(sprintf(_('Invalid embed URL. Only %s URLs are supported.'), implode('/', array_keys($tinyib_embeds))));
|
||||
fancyDie(sprintf(__('Invalid embed URL. Only %s URLs are supported.'), implode('/', array_keys($tinyib_embeds))));
|
||||
}
|
||||
|
||||
$post['file_hex'] = $service;
|
||||
|
@ -193,14 +195,14 @@ if (!isset($_GET['delete']) && !isset($_GET['manage']) && (isset($_POST['name'])
|
|||
} else if ($file_mime == "image/png") {
|
||||
$post['thumb'] = $temp_file . '.png';
|
||||
} else {
|
||||
fancyDie(_('Error while processing audio/video.'));
|
||||
fancyDie(__('Error while processing audio/video.'));
|
||||
}
|
||||
$thumb_location = "thumb/" . $post['thumb'];
|
||||
|
||||
list($thumb_maxwidth, $thumb_maxheight) = thumbnailDimensions($post);
|
||||
|
||||
if (!createThumbnail($file_location, $thumb_location, $thumb_maxwidth, $thumb_maxheight)) {
|
||||
fancyDie(_('Could not create thumbnail.'));
|
||||
fancyDie(__('Could not create thumbnail.'));
|
||||
}
|
||||
|
||||
addVideoOverlay($thumb_location);
|
||||
|
@ -216,11 +218,11 @@ if (!isset($_GET['delete']) && !isset($_GET['manage']) && (isset($_POST['name'])
|
|||
validateFileUpload();
|
||||
|
||||
if (!is_file($_FILES['file']['tmp_name']) || !is_readable($_FILES['file']['tmp_name'])) {
|
||||
fancyDie(_('File transfer failure. Please retry the submission.'));
|
||||
fancyDie(__('File transfer failure. Please retry the submission.'));
|
||||
}
|
||||
|
||||
if ((TINYIB_MAXKB > 0) && (filesize($_FILES['file']['tmp_name']) > (TINYIB_MAXKB * 1024))) {
|
||||
fancyDie(sprintf(_('That file is larger than %s.'), TINYIB_MAXKBDESC));
|
||||
fancyDie(sprintf(__('That file is larger than %s.'), TINYIB_MAXKBDESC));
|
||||
}
|
||||
|
||||
$post['file_original'] = trim(htmlentities(substr($_FILES['file']['name'], 0, 50), ENT_QUOTES));
|
||||
|
@ -235,7 +237,7 @@ if (!isset($_GET['delete']) && !isset($_GET['manage']) && (isset($_POST['name'])
|
|||
$file_mime = strtolower(array_pop($file_mime_split));
|
||||
} else {
|
||||
if (!@getimagesize($_FILES['file']['tmp_name'])) {
|
||||
fancyDie(_('Failed to read the MIME type and size of the uploaded file. Please retry the submission.'));
|
||||
fancyDie(__('Failed to read the MIME type and size of the uploaded file. Please retry the submission.'));
|
||||
}
|
||||
|
||||
$file_info = getimagesize($_FILES['file']['tmp_name']);
|
||||
|
@ -251,12 +253,12 @@ if (!isset($_GET['delete']) && !isset($_GET['manage']) && (isset($_POST['name'])
|
|||
|
||||
$file_location = "src/" . $post['file'];
|
||||
if (!move_uploaded_file($_FILES['file']['tmp_name'], $file_location)) {
|
||||
fancyDie(_('Could not copy uploaded file.'));
|
||||
fancyDie(__('Could not copy uploaded file.'));
|
||||
}
|
||||
|
||||
if ($_FILES['file']['size'] != filesize($file_location)) {
|
||||
@unlink($file_location);
|
||||
fancyDie(_('File transfer failure. Please go back and try again.'));
|
||||
fancyDie(__('File transfer failure. Please go back and try again.'));
|
||||
}
|
||||
|
||||
if ($file_mime == "audio/webm" || $file_mime == "video/webm" || $file_mime == "audio/mp4" || $file_mime == "video/mp4") {
|
||||
|
@ -275,7 +277,7 @@ if (!isset($_GET['delete']) && !isset($_GET['manage']) && (isset($_POST['name'])
|
|||
if ($post['thumb_width'] <= 0 || $post['thumb_height'] <= 0) {
|
||||
@unlink($file_location);
|
||||
@unlink("thumb/" . $post['thumb']);
|
||||
fancyDie(_('Sorry, your video appears to be corrupt.'));
|
||||
fancyDie(__('Sorry, your video appears to be corrupt.'));
|
||||
}
|
||||
|
||||
addVideoOverlay("thumb/" . $post['thumb']);
|
||||
|
@ -300,7 +302,7 @@ if (!isset($_GET['delete']) && !isset($_GET['manage']) && (isset($_POST['name'])
|
|||
$post['thumb'] = $file_name . "s." . array_pop($thumbfile_split);
|
||||
if (!copy($tinyib_uploads[$file_mime][1], "thumb/" . $post['thumb'])) {
|
||||
@unlink($file_location);
|
||||
fancyDie(_('Could not create thumbnail.'));
|
||||
fancyDie(__('Could not create thumbnail.'));
|
||||
}
|
||||
if ($file_mime == "application/x-shockwave-flash") {
|
||||
addVideoOverlay("thumb/" . $post['thumb']);
|
||||
|
@ -311,7 +313,7 @@ if (!isset($_GET['delete']) && !isset($_GET['manage']) && (isset($_POST['name'])
|
|||
|
||||
if (!createThumbnail($file_location, "thumb/" . $post['thumb'], $thumb_maxwidth, $thumb_maxheight)) {
|
||||
@unlink($file_location);
|
||||
fancyDie(_('Could not create thumbnail.'));
|
||||
fancyDie(__('Could not create thumbnail.'));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -335,7 +337,7 @@ if (!isset($_GET['delete']) && !isset($_GET['manage']) && (isset($_POST['name'])
|
|||
$allowed .= "embed URL";
|
||||
}
|
||||
if ($post['parent'] == TINYIB_NEWTHREAD && $allowed != "" && !TINYIB_NOFILEOK) {
|
||||
fancyDie(sprintf(_('A %s is required to start a thread.'), $allowed));
|
||||
fancyDie(sprintf(__('A %s is required to start a thread.'), $allowed));
|
||||
}
|
||||
if (!$rawpost && str_replace('<br>', '', $post['message']) == "") {
|
||||
$die_msg = "";
|
||||
|
@ -348,12 +350,12 @@ if (!isset($_GET['delete']) && !isset($_GET['manage']) && (isset($_POST['name'])
|
|||
fancyDie("Please $die_msg.");
|
||||
}
|
||||
} else {
|
||||
echo sprintf(_('%s uploaded.'), $post['file_original']) . '<br>';
|
||||
echo sprintf(__('%s uploaded.'), $post['file_original']) . '<br>';
|
||||
}
|
||||
|
||||
if (!$loggedin && (($post['file'] != '' && TINYIB_REQMOD == 'files') || TINYIB_REQMOD == 'all')) {
|
||||
$post['moderated'] = '0';
|
||||
echo sprintf(_('Your %s will be shown <b>once it has been approved</b>.'), $post['parent'] == TINYIB_NEWTHREAD ? 'thread' : 'post') . '<br>';
|
||||
echo sprintf(__('Your %s will be shown <b>once it has been approved</b>.'), $post['parent'] == TINYIB_NEWTHREAD ? 'thread' : 'post') . '<br>';
|
||||
$slow_redirect = true;
|
||||
}
|
||||
|
||||
|
@ -366,7 +368,7 @@ if (!isset($_GET['delete']) && !isset($_GET['manage']) && (isset($_POST['name'])
|
|||
|
||||
trimThreads();
|
||||
|
||||
echo _('Updating thread...') . '<br>';
|
||||
echo __('Updating thread...') . '<br>';
|
||||
if ($post['parent'] != TINYIB_NEWTHREAD) {
|
||||
rebuildThread($post['parent']);
|
||||
|
||||
|
@ -379,17 +381,17 @@ if (!isset($_GET['delete']) && !isset($_GET['manage']) && (isset($_POST['name'])
|
|||
rebuildThread($post['id']);
|
||||
}
|
||||
|
||||
echo _('Updating index...') . '<br>';
|
||||
echo __('Updating index...') . '<br>';
|
||||
rebuildIndexes();
|
||||
}
|
||||
// Check if the request is to delete a post and/or its associated image
|
||||
} elseif (isset($_GET['delete']) && !isset($_GET['manage'])) {
|
||||
if (!isset($_POST['delete'])) {
|
||||
fancyDie(_('Tick the box next to a post and click "Delete" to delete it.'));
|
||||
fancyDie(__('Tick the box next to a post and click "Delete" to delete it.'));
|
||||
}
|
||||
|
||||
if (TINYIB_DBMIGRATE) {
|
||||
fancyDie(_('Post deletion is currently disabled.<br>Please try again in a few moments.'));
|
||||
fancyDie(__('Post deletion is currently disabled.<br>Please try again in a few moments.'));
|
||||
}
|
||||
|
||||
$post = postByID($_POST['delete']);
|
||||
|
@ -406,12 +408,12 @@ if (!isset($_GET['delete']) && !isset($_GET['manage']) && (isset($_POST['name'])
|
|||
} else {
|
||||
threadUpdated($post['parent']);
|
||||
}
|
||||
fancyDie(_('Post deleted.'));
|
||||
fancyDie(__('Post deleted.'));
|
||||
} else {
|
||||
fancyDie(_('Invalid password.'));
|
||||
fancyDie(__('Invalid password.'));
|
||||
}
|
||||
} else {
|
||||
fancyDie(_('Sorry, an invalid post identifier was sent. Please go back, refresh the page, and try again.'));
|
||||
fancyDie(__('Sorry, an invalid post identifier was sent. Please go back, refresh the page, and try again.'));
|
||||
}
|
||||
|
||||
$redirect = false;
|
||||
|
@ -435,7 +437,7 @@ if (!isset($_GET['delete']) && !isset($_GET['manage']) && (isset($_POST['name'])
|
|||
rebuildThread($thread['id']);
|
||||
}
|
||||
rebuildIndexes();
|
||||
$text .= manageInfo(_('Rebuilt board.'));
|
||||
$text .= manageInfo(__('Rebuilt board.'));
|
||||
} elseif (isset($_GET['bans'])) {
|
||||
clearExpiredBans();
|
||||
|
||||
|
@ -443,7 +445,7 @@ if (!isset($_GET['delete']) && !isset($_GET['manage']) && (isset($_POST['name'])
|
|||
if ($_POST['ip'] != '') {
|
||||
$banexists = banByIP($_POST['ip']);
|
||||
if ($banexists) {
|
||||
fancyDie(_('Sorry, there is already a ban on record for that IP address.'));
|
||||
fancyDie(__('Sorry, there is already a ban on record for that IP address.'));
|
||||
}
|
||||
|
||||
$ban = array();
|
||||
|
@ -452,13 +454,13 @@ if (!isset($_GET['delete']) && !isset($_GET['manage']) && (isset($_POST['name'])
|
|||
$ban['reason'] = $_POST['reason'];
|
||||
|
||||
insertBan($ban);
|
||||
$text .= manageInfo(sprintf(_('Ban record added for %s'), $ban['ip']));
|
||||
$text .= manageInfo(sprintf(__('Ban record added for %s'), $ban['ip']));
|
||||
}
|
||||
} elseif (isset($_GET['lift'])) {
|
||||
$ban = banByID($_GET['lift']);
|
||||
if ($ban) {
|
||||
deleteBanByID($_GET['lift']);
|
||||
$text .= manageInfo(sprintf(_('Ban record lifted for %s'), $ban['ip']));
|
||||
$text .= manageInfo(sprintf(__('Ban record lifted for %s'), $ban['ip']));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -550,9 +552,9 @@ if (!isset($_GET['delete']) && !isset($_GET['manage']) && (isset($_POST['name'])
|
|||
if ($post['parent'] != TINYIB_NEWTHREAD) {
|
||||
rebuildThread($post['parent']);
|
||||
}
|
||||
$text .= manageInfo(sprintf(_('Post No.%d deleted.'), $post['id']));
|
||||
$text .= manageInfo(sprintf(__('Post No.%d deleted.'), $post['id']));
|
||||
} else {
|
||||
fancyDie(_("Sorry, there doesn't appear to be a post with that ID."));
|
||||
fancyDie(__("Sorry, there doesn't appear to be a post with that ID."));
|
||||
}
|
||||
} elseif (isset($_GET['approve'])) {
|
||||
if ($_GET['approve'] > 0) {
|
||||
|
@ -566,9 +568,9 @@ if (!isset($_GET['delete']) && !isset($_GET['manage']) && (isset($_POST['name'])
|
|||
}
|
||||
threadUpdated($thread_id);
|
||||
|
||||
$text .= manageInfo(sprintf(_('Post No.%d approved.'), $post['id']));
|
||||
$text .= manageInfo(sprintf(__('Post No.%d approved.'), $post['id']));
|
||||
} else {
|
||||
fancyDie(_("Sorry, there doesn't appear to be a post with that ID."));
|
||||
fancyDie(__("Sorry, there doesn't appear to be a post with that ID."));
|
||||
}
|
||||
}
|
||||
} elseif (isset($_GET['moderate'])) {
|
||||
|
@ -577,7 +579,7 @@ if (!isset($_GET['delete']) && !isset($_GET['manage']) && (isset($_POST['name'])
|
|||
if ($post) {
|
||||
$text .= manageModeratePost($post);
|
||||
} else {
|
||||
fancyDie(_("Sorry, there doesn't appear to be a post with that ID."));
|
||||
fancyDie(__("Sorry, there doesn't appear to be a post with that ID."));
|
||||
}
|
||||
} else {
|
||||
$onload = manageOnLoad('moderate');
|
||||
|
@ -592,10 +594,10 @@ if (!isset($_GET['delete']) && !isset($_GET['manage']) && (isset($_POST['name'])
|
|||
|
||||
$text .= manageInfo('Thread No.' . $post['id'] . ' ' . (intval($_GET['setsticky']) == 1 ? 'stickied' : 'un-stickied') . '.');
|
||||
} else {
|
||||
fancyDie(_("Sorry, there doesn't appear to be a post with that ID."));
|
||||
fancyDie(__("Sorry, there doesn't appear to be a post with that ID."));
|
||||
}
|
||||
} else {
|
||||
fancyDie(_('Form data was lost. Please go back and try again.'));
|
||||
fancyDie(__('Form data was lost. Please go back and try again.'));
|
||||
}
|
||||
} elseif (isset($_GET['lock']) && isset($_GET['setlock'])) {
|
||||
if ($_GET['lock'] > 0) {
|
||||
|
@ -606,10 +608,10 @@ if (!isset($_GET['delete']) && !isset($_GET['manage']) && (isset($_POST['name'])
|
|||
|
||||
$text .= manageInfo('Thread No.' . $post['id'] . ' ' . (intval($_GET['setlock']) == 1 ? 'locked' : 'unlocked') . '.');
|
||||
} else {
|
||||
fancyDie(_("Sorry, there doesn't appear to be a post with that ID."));
|
||||
fancyDie(__("Sorry, there doesn't appear to be a post with that ID."));
|
||||
}
|
||||
} else {
|
||||
fancyDie(_('Form data was lost. Please go back and try again.'));
|
||||
fancyDie(__('Form data was lost. Please go back and try again.'));
|
||||
}
|
||||
} elseif (isset($_GET["rawpost"])) {
|
||||
$onload = manageOnLoad("rawpost");
|
||||
|
|
|
@ -211,7 +211,7 @@ function nameAndTripcode($name) {
|
|||
|
||||
function nameBlock($name, $tripcode, $email, $timestamp, $rawposttext) {
|
||||
$output = '<span class="postername">';
|
||||
$output .= ($name == '' && $tripcode == '') ? _('Anonymous') : $name;
|
||||
$output .= ($name == '' && $tripcode == '') ? __('Anonymous') : $name;
|
||||
|
||||
if ($tripcode != '') {
|
||||
$output .= '</span><span class="postertrip">!' . $tripcode;
|
||||
|
@ -320,9 +320,9 @@ function checkCAPTCHA() {
|
|||
$captcha_solution = isset($_SESSION['tinyibcaptcha']) ? strtolower(trim($_SESSION['tinyibcaptcha'])) : '';
|
||||
|
||||
if ($captcha == '') {
|
||||
fancyDie(_('Please enter the CAPTCHA text.'));
|
||||
fancyDie(__('Please enter the CAPTCHA text.'));
|
||||
} else if ($captcha != $captcha_solution) {
|
||||
fancyDie(_('Incorrect CAPTCHA text entered. Please try again.<br>Click the image to retrieve a new CAPTCHA.'));
|
||||
fancyDie(__('Incorrect CAPTCHA text entered. Please try again.<br>Click the image to retrieve a new CAPTCHA.'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -353,7 +353,7 @@ function checkFlood() {
|
|||
|
||||
function checkMessageSize() {
|
||||
if (strlen($_POST["message"]) > 8000) {
|
||||
fancyDie(sprintf(_('Please shorten your message, or post it in multiple parts. Your message is %1$d characters long, and the maximum allowed is %2$d.'), strlen($_POST["message"]), 8000));
|
||||
fancyDie(sprintf(__('Please shorten your message, or post it in multiple parts. Your message is %1$d characters long, and the maximum allowed is %2$d.'), strlen($_POST["message"]), 8000));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -384,7 +384,7 @@ function setParent() {
|
|||
if (isset($_POST["parent"])) {
|
||||
if ($_POST["parent"] != TINYIB_NEWTHREAD) {
|
||||
if (!threadExistsByID($_POST['parent'])) {
|
||||
fancyDie(_('Invalid parent thread ID supplied, unable to create post.'));
|
||||
fancyDie(__('Invalid parent thread ID supplied, unable to create post.'));
|
||||
}
|
||||
|
||||
return $_POST["parent"];
|
||||
|
@ -410,25 +410,25 @@ function validateFileUpload() {
|
|||
case UPLOAD_ERR_OK:
|
||||
break;
|
||||
case UPLOAD_ERR_FORM_SIZE:
|
||||
fancyDie(sprintf(_('That file is larger than %s.'), TINYIB_MAXKBDESC));
|
||||
fancyDie(sprintf(__('That file is larger than %s.'), TINYIB_MAXKBDESC));
|
||||
break;
|
||||
case UPLOAD_ERR_INI_SIZE:
|
||||
fancyDie(sprintf(_('The uploaded file exceeds the upload_max_filesize directive (%s) in php.ini.'), ini_get('upload_max_filesize')));
|
||||
fancyDie(sprintf(__('The uploaded file exceeds the upload_max_filesize directive (%s) in php.ini.'), ini_get('upload_max_filesize')));
|
||||
break;
|
||||
case UPLOAD_ERR_PARTIAL:
|
||||
fancyDie(_('The uploaded file was only partially uploaded.'));
|
||||
fancyDie(__('The uploaded file was only partially uploaded.'));
|
||||
break;
|
||||
case UPLOAD_ERR_NO_FILE:
|
||||
fancyDie(_('No file was uploaded.'));
|
||||
fancyDie(__('No file was uploaded.'));
|
||||
break;
|
||||
case UPLOAD_ERR_NO_TMP_DIR:
|
||||
fancyDie(_('Missing a temporary folder.'));
|
||||
fancyDie(__('Missing a temporary folder.'));
|
||||
break;
|
||||
case UPLOAD_ERR_CANT_WRITE:
|
||||
fancyDie(_('Failed to write file to disk'));
|
||||
fancyDie(__('Failed to write file to disk'));
|
||||
break;
|
||||
default:
|
||||
fancyDie(_('Unable to save the uploaded file.'));
|
||||
fancyDie(__('Unable to save the uploaded file.'));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -436,7 +436,7 @@ function checkDuplicateFile($hex) {
|
|||
$hexmatches = postsByHex($hex);
|
||||
if (count($hexmatches) > 0) {
|
||||
foreach ($hexmatches as $hexmatch) {
|
||||
fancyDie(sprintf(_('Duplicate file uploaded. That file has already been posted <a href="%s">here</a>.'), 'res/' . (($hexmatch['parent'] == TINYIB_NEWTHREAD) ? $hexmatch['id'] : $hexmatch['parent'])) . '.html#' . $hexmatch['id']);
|
||||
fancyDie(sprintf(__('Duplicate file uploaded. That file has already been posted <a href="%s">here</a>.'), 'res/' . (($hexmatch['parent'] == TINYIB_NEWTHREAD) ? $hexmatch['id'] : $hexmatch['parent'])) . '.html#' . $hexmatch['id']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -467,7 +467,7 @@ function createThumbnail($file_location, $thumb_location, $new_w, $new_h) {
|
|||
}
|
||||
|
||||
if (!$src_img) {
|
||||
fancyDie(_('Unable to read the uploaded file while creating its thumbnail. A common cause for this is an incorrect extension when the file is actually of a different type.'));
|
||||
fancyDie(__('Unable to read the uploaded file while creating its thumbnail. A common cause for this is an incorrect extension when the file is actually of a different type.'));
|
||||
}
|
||||
|
||||
$old_x = imageSX($src_img);
|
||||
|
|
172
inc/gettext/CHANGELOG.md
Normal file
172
inc/gettext/CHANGELOG.md
Normal file
|
@ -0,0 +1,172 @@
|
|||
# Change Log
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](http://keepachangelog.com/)
|
||||
and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
Previous releases are documented in [github releases](https://github.com/oscarotero/Gettext/releases)
|
||||
|
||||
## [4.8.2] - 2019-12-02
|
||||
### Fixed
|
||||
- UTF-8 handling for VueJs extractor [#242]
|
||||
|
||||
## [4.8.1] - 2019-11-15
|
||||
### Fixed
|
||||
- Php error when scanning for a single domain but other string found [#238]
|
||||
|
||||
## [4.8.0] - 2019-11-04
|
||||
### Changed
|
||||
- Many `private` properties and methods were changed to `protected` in order to improve the extensibility [#231]
|
||||
|
||||
### Fixed
|
||||
- PHP 7.4 support [#230]
|
||||
|
||||
## [4.7.0] - 2019-10-07
|
||||
### Added
|
||||
- Support for UnitID in Xliff [#221] [#224] [#225]
|
||||
- Support for scan multiple domains at the same time [#223]
|
||||
|
||||
### Fixed
|
||||
- New lines in windows [#218] [#226]
|
||||
|
||||
## [4.6.3] - 2019-07-15
|
||||
### Added
|
||||
- Some VueJs extraction improvements and additions [#205], [#213]
|
||||
|
||||
### Fixed
|
||||
- Multiline extractions in jsCode [#200]
|
||||
- Support for js template literals [#214]
|
||||
- Fixed tabs in PHP comments [#215]
|
||||
|
||||
## [4.6.2] - 2019-01-12
|
||||
### Added
|
||||
- New option `facade` in blade extractor to use a facade instead create a blade compiler [#197], [#198]
|
||||
|
||||
### Fixed
|
||||
- Added php-7.3 to travis
|
||||
- Added VueJS extractor method docblocks for IDEs [#191]
|
||||
|
||||
## [4.6.1] - 2018-08-27
|
||||
### Fixed
|
||||
- VueJS DOM parsing [#188]
|
||||
- Javascript parser was unable to extract some functions [#187]
|
||||
|
||||
## [4.6.0] - 2018-06-26
|
||||
### Added
|
||||
- New extractor for VueJs [#178]
|
||||
|
||||
### Fixed
|
||||
- Do not include empty translations containing the headers in the translator [#182]
|
||||
- Test enhancement [#177]
|
||||
|
||||
## [4.5.0] - 2018-04-23
|
||||
### Added
|
||||
- Support for disabled translations
|
||||
|
||||
### Fixed
|
||||
- Added php-7.2 to travis
|
||||
- Fixed po tests on bigendian [#159]
|
||||
- Improved comment estraction [#166]
|
||||
- Fixed incorrect docs to dn__ function [#170]
|
||||
- Ignored phpcs.xml file on export [#168]
|
||||
- Improved `@method` docs in `Translations` [#175]
|
||||
|
||||
## [4.4.4] - 2018-02-21
|
||||
### Fixed
|
||||
- Changed the comment extraction to be compatible with gettext behaviour: the comment must be placed in the line preceding the function [#161]
|
||||
|
||||
### Security
|
||||
- Validate eval input from plural forms [#156]
|
||||
|
||||
## [4.4.3] - 2017-08-09
|
||||
### Fixed
|
||||
- Handle `NULL` arguments on extract entries in php. For example `dn__(null, 'singular', 'plural')`.
|
||||
- Fixed the `PhpCode` and `JsCode` extractors that didn't extract `dn__` and `dngettext` entries [#155].
|
||||
- Fixed the `PhpCode` and `JsCode` extractors that didn't extract `dnpgettext` correctly.
|
||||
|
||||
## [4.4.2] - 2017-07-27
|
||||
### Fixed
|
||||
- Clone the translations in `Translations::mergeWith` to prevent that the translation is referenced in both places. [#152]
|
||||
- Fixed escaped quotes in the javascript extractor [#154]
|
||||
|
||||
## [4.4.1] - 2017-05-20
|
||||
### Fixed
|
||||
- Fixed a bug where the options was not passed correctly to the merging Translations object [#147]
|
||||
- Unified the plural behaviours between PHP gettext and Translator when the plural translation is unknown [#148]
|
||||
- Removed the deprecated function `create_function()` and use `eval()` instead
|
||||
|
||||
## [4.4.0] - 2017-05-10
|
||||
### Added
|
||||
- New option `noLocation` to po generator, to omit the references [#143]
|
||||
- New options `delimiter`, `enclosure` and `escape_char` to Csv and CsvDictionary extractors and generators [#145]
|
||||
- Added the missing `dn__()` function [#146]
|
||||
|
||||
### Fixed
|
||||
- Improved the code style including php_codesniffer in development
|
||||
|
||||
## 4.3.0 - 2017-03-04
|
||||
### Added
|
||||
- Added support for named placeholders (using `strtr`). For example:
|
||||
```php
|
||||
__('Hello :name', [':name' => 'World']);
|
||||
```
|
||||
- Added support for Twig v2
|
||||
- New function `BaseTranslator::includeFunctions()` to include the functions file without register any translator
|
||||
|
||||
### Fixed
|
||||
- Fixed a bug related with the javascript source extraction with single quotes
|
||||
|
||||
[#143]: https://github.com/oscarotero/Gettext/issues/143
|
||||
[#145]: https://github.com/oscarotero/Gettext/issues/145
|
||||
[#146]: https://github.com/oscarotero/Gettext/issues/146
|
||||
[#147]: https://github.com/oscarotero/Gettext/issues/147
|
||||
[#148]: https://github.com/oscarotero/Gettext/issues/148
|
||||
[#152]: https://github.com/oscarotero/Gettext/issues/152
|
||||
[#154]: https://github.com/oscarotero/Gettext/issues/154
|
||||
[#155]: https://github.com/oscarotero/Gettext/issues/155
|
||||
[#156]: https://github.com/oscarotero/Gettext/issues/156
|
||||
[#159]: https://github.com/oscarotero/Gettext/issues/159
|
||||
[#161]: https://github.com/oscarotero/Gettext/issues/161
|
||||
[#166]: https://github.com/oscarotero/Gettext/issues/166
|
||||
[#168]: https://github.com/oscarotero/Gettext/issues/168
|
||||
[#170]: https://github.com/oscarotero/Gettext/issues/170
|
||||
[#175]: https://github.com/oscarotero/Gettext/issues/175
|
||||
[#177]: https://github.com/oscarotero/Gettext/issues/177
|
||||
[#178]: https://github.com/oscarotero/Gettext/issues/178
|
||||
[#182]: https://github.com/oscarotero/Gettext/issues/182
|
||||
[#187]: https://github.com/oscarotero/Gettext/issues/187
|
||||
[#188]: https://github.com/oscarotero/Gettext/issues/188
|
||||
[#191]: https://github.com/oscarotero/Gettext/issues/191
|
||||
[#197]: https://github.com/oscarotero/Gettext/issues/197
|
||||
[#198]: https://github.com/oscarotero/Gettext/issues/198
|
||||
[#200]: https://github.com/oscarotero/Gettext/issues/200
|
||||
[#205]: https://github.com/oscarotero/Gettext/issues/205
|
||||
[#213]: https://github.com/oscarotero/Gettext/issues/213
|
||||
[#214]: https://github.com/oscarotero/Gettext/issues/214
|
||||
[#215]: https://github.com/oscarotero/Gettext/issues/215
|
||||
[#218]: https://github.com/oscarotero/Gettext/issues/218
|
||||
[#221]: https://github.com/oscarotero/Gettext/issues/221
|
||||
[#223]: https://github.com/oscarotero/Gettext/issues/223
|
||||
[#224]: https://github.com/oscarotero/Gettext/issues/224
|
||||
[#225]: https://github.com/oscarotero/Gettext/issues/225
|
||||
[#226]: https://github.com/oscarotero/Gettext/issues/226
|
||||
[#230]: https://github.com/oscarotero/Gettext/issues/230
|
||||
[#231]: https://github.com/oscarotero/Gettext/issues/231
|
||||
[#238]: https://github.com/oscarotero/Gettext/issues/238
|
||||
[#242]: https://github.com/oscarotero/Gettext/issues/242
|
||||
|
||||
[4.8.2]: https://github.com/oscarotero/Gettext/compare/v4.8.1...v4.8.2
|
||||
[4.8.1]: https://github.com/oscarotero/Gettext/compare/v4.8.0...v4.8.1
|
||||
[4.8.0]: https://github.com/oscarotero/Gettext/compare/v4.7.0...v4.8.0
|
||||
[4.7.0]: https://github.com/oscarotero/Gettext/compare/v4.6.3...v4.7.0
|
||||
[4.6.3]: https://github.com/oscarotero/Gettext/compare/v4.6.2...v4.6.3
|
||||
[4.6.2]: https://github.com/oscarotero/Gettext/compare/v4.6.1...v4.6.2
|
||||
[4.6.1]: https://github.com/oscarotero/Gettext/compare/v4.6.0...v4.6.1
|
||||
[4.6.0]: https://github.com/oscarotero/Gettext/compare/v4.5.0...v4.6.0
|
||||
[4.5.0]: https://github.com/oscarotero/Gettext/compare/v4.4.4...v4.5.0
|
||||
[4.4.4]: https://github.com/oscarotero/Gettext/compare/v4.4.3...v4.4.4
|
||||
[4.4.3]: https://github.com/oscarotero/Gettext/compare/v4.4.2...v4.4.3
|
||||
[4.4.2]: https://github.com/oscarotero/Gettext/compare/v4.4.1...v4.4.2
|
||||
[4.4.1]: https://github.com/oscarotero/Gettext/compare/v4.4.0...v4.4.1
|
||||
[4.4.0]: https://github.com/oscarotero/Gettext/compare/v4.3.0...v4.4.0
|
17
inc/gettext/CONTRIBUTING.md
Normal file
17
inc/gettext/CONTRIBUTING.md
Normal file
|
@ -0,0 +1,17 @@
|
|||
Contributing to Gettext
|
||||
=======================
|
||||
|
||||
Looking to contribute something to this library? Here's how you can help.
|
||||
|
||||
## Bugs
|
||||
|
||||
A bug is a demonstrable problem that is caused by the code in the repository. Good bug reports are extremely helpful – thank you!
|
||||
|
||||
Please try to be as detailed as possible in your report. Include specific information about the environment – version of PHP, version of gettext, etc, and steps required to reproduce the issue.
|
||||
|
||||
## Pull Requests
|
||||
|
||||
Good pull requests – patches, improvements, new features – are a fantastic help. New extractors or generator are welcome. Before create a pull request, please follow these instructions:
|
||||
|
||||
* The code must be PSR-2 compliant
|
||||
* Write some tests
|
21
inc/gettext/LICENSE
Normal file
21
inc/gettext/LICENSE
Normal file
|
@ -0,0 +1,21 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017 Oscar Otero Marzoa
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
425
inc/gettext/README.md
Normal file
425
inc/gettext/README.md
Normal file
|
@ -0,0 +1,425 @@
|
|||
Gettext
|
||||
=======
|
||||
|
||||
[![Build Status](https://travis-ci.org/oscarotero/Gettext.png?branch=master)](https://travis-ci.org/oscarotero/Gettext)
|
||||
[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/oscarotero/Gettext/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/oscarotero/Gettext/?branch=master)
|
||||
[![Latest Stable Version](https://poser.pugx.org/gettext/gettext/v/stable.svg)](https://packagist.org/packages/gettext/gettext)
|
||||
[![Total Downloads](https://poser.pugx.org/gettext/gettext/downloads.svg)](https://packagist.org/packages/gettext/gettext)
|
||||
[![Monthly Downloads](https://poser.pugx.org/gettext/gettext/d/monthly.png)](https://packagist.org/packages/gettext/gettext)
|
||||
[![License](https://poser.pugx.org/gettext/gettext/license.svg)](https://packagist.org/packages/gettext/gettext)
|
||||
|
||||
[![SensioLabsInsight](https://insight.sensiolabs.com/projects/496dc2a6-43be-4046-a283-f8370239dd47/big.png)](https://insight.sensiolabs.com/projects/496dc2a6-43be-4046-a283-f8370239dd47)
|
||||
|
||||
Created by Oscar Otero <http://oscarotero.com> <oom@oscarotero.com> (MIT License)
|
||||
|
||||
Gettext is a PHP (>=5.4) library to import/export/edit gettext from PO, MO, PHP, JS files, etc.
|
||||
|
||||
## Installation
|
||||
|
||||
With composer (recomended):
|
||||
|
||||
```
|
||||
composer require gettext/gettext
|
||||
```
|
||||
|
||||
If you don't use composer in your project, you have to download and place this package in a directory of your project. You need to install also [gettext/languages](https://github.com/mlocati/cldr-to-gettext-plural-rules). Then, include the autoloaders of both projects in any place of your php code:
|
||||
|
||||
```php
|
||||
include_once "libs/gettext/src/autoloader.php";
|
||||
include_once "libs/cldr-to-gettext-plural-rules/src/autoloader.php";
|
||||
```
|
||||
|
||||
## Classes and functions
|
||||
|
||||
This package contains the following classes:
|
||||
|
||||
* `Gettext\Translation` - A translation definition
|
||||
* `Gettext\Translations` - A collection of translations
|
||||
* `Gettext\Extractors\*` - Import translations from various sources (po, mo, php, js, etc)
|
||||
* `Gettext\Generators\*` - Export translations to various formats (po, mo, php, json, etc)
|
||||
* `Gettext\Translator` - To use the translations in your php templates instead the [gettext extension](http://php.net/gettext)
|
||||
* `Gettext\GettextTranslator` - To use the [gettext extension](http://php.net/gettext)
|
||||
|
||||
## Usage example
|
||||
|
||||
```php
|
||||
use Gettext\Translations;
|
||||
|
||||
//import from a .po file:
|
||||
$translations = Translations::fromPoFile('locales/gl.po');
|
||||
|
||||
//edit some translations:
|
||||
$translation = $translations->find(null, 'apple');
|
||||
|
||||
if ($translation) {
|
||||
$translation->setTranslation('Mazá');
|
||||
}
|
||||
|
||||
//export to a php array:
|
||||
$translations->toPhpArrayFile('locales/gl.php');
|
||||
|
||||
//and to a .mo file
|
||||
$translations->toMoFile('Locale/gl/LC_MESSAGES/messages.mo');
|
||||
```
|
||||
|
||||
If you want use this translations in your php templates without using the gettext extension:
|
||||
|
||||
```php
|
||||
use Gettext\Translator;
|
||||
|
||||
//Create the translator instance
|
||||
$t = new Translator();
|
||||
|
||||
//Load your translations (exported as PhpArray):
|
||||
$t->loadTranslations('locales/gl.php');
|
||||
|
||||
//Use it:
|
||||
echo $t->gettext('apple'); // "Mazá"
|
||||
|
||||
//If you want use global functions:
|
||||
$t->register();
|
||||
|
||||
echo __('apple'); // "Mazá"
|
||||
```
|
||||
|
||||
To use this translations with the gettext extension:
|
||||
|
||||
```php
|
||||
use Gettext\GettextTranslator;
|
||||
|
||||
//Create the translator instance
|
||||
$t = new GettextTranslator();
|
||||
|
||||
//Set the language and load the domain
|
||||
$t->setLanguage('gl');
|
||||
$t->loadDomain('messages', 'Locale');
|
||||
|
||||
//Use it:
|
||||
echo $t->gettext('apple'); // "Mazá"
|
||||
|
||||
//Or use the gettext functions
|
||||
echo gettext('apple'); // "Mazá"
|
||||
|
||||
//If you want use the global functions
|
||||
$t->register();
|
||||
|
||||
echo __('apple'); // "Mazá"
|
||||
|
||||
//And use sprintf/strtr placeholders
|
||||
echo __('Hello %s', 'world'); //Hello world
|
||||
echo __('Hello {name}', ['{name}' => 'world']); //Hello world
|
||||
```
|
||||
|
||||
The benefits of using the functions provided by this library (`__()` instead `_()` or `gettext()`) are:
|
||||
|
||||
* You are using the same functions, no matter whether the translations are provided by gettext extension or any other method.
|
||||
* You can use variables easier because `sprintf` functionality is included. For example: `__('Hello %s', 'world')` instead `sprintf(_('Hello %s'), 'world')`.
|
||||
* You can also use named placeholders if the second argument is an array. For example: `__('Hello %name%', ['%name%' => 'world'])` instead of `strtr(_('Hello %name%'), ['%name%' => 'world'])`.
|
||||
|
||||
## Translation
|
||||
|
||||
The `Gettext\Translation` class stores all information about a translation: the original text, the translated text, source references, comments, etc.
|
||||
|
||||
```php
|
||||
// __construct($context, $original, $plural)
|
||||
$translation = new Gettext\Translation('comments', 'One comment', '%s comments');
|
||||
|
||||
$translation->setTranslation('Un comentario');
|
||||
$translation->setPluralTranslation('%s comentarios');
|
||||
|
||||
$translation->addReference('templates/comments/comment.php', 34);
|
||||
$translation->addComment('To display the amount of comments in a post');
|
||||
|
||||
echo $translation->getContext(); // comments
|
||||
echo $translation->getOriginal(); // One comment
|
||||
echo $translation->getTranslation(); // Un comentario
|
||||
|
||||
// etc...
|
||||
```
|
||||
|
||||
## Translations
|
||||
|
||||
The `Gettext\Translations` class stores a collection of translations:
|
||||
|
||||
```php
|
||||
$translations = new Gettext\Translations();
|
||||
|
||||
//You can add new translations using the array syntax
|
||||
$translations[] = new Gettext\Translation('comments', 'One comment', '%s comments');
|
||||
|
||||
//Or using the "insert" method
|
||||
$insertedTranslation = $translations->insert('comments', 'One comment', '%s comments');
|
||||
|
||||
//Find a specific translation
|
||||
$translation = $translations->find('comments', 'One comment');
|
||||
|
||||
//Edit headers, domain, etc
|
||||
$translations->setHeader('Last-Translator', 'Oscar Otero');
|
||||
$translations->setDomain('my-blog');
|
||||
```
|
||||
|
||||
## Extractors
|
||||
|
||||
The extrators allows to fetch gettext values from any source. For example, to scan a .po file:
|
||||
|
||||
```php
|
||||
$translations = new Gettext\Translations();
|
||||
|
||||
//From a file
|
||||
Gettext\Extractors\Po::fromFile('locales/en.po', $translations);
|
||||
|
||||
//From a string
|
||||
$string = file_get_contents('locales2/en.po');
|
||||
Gettext\Extractors\Po::fromString($string, $translations);
|
||||
```
|
||||
|
||||
The better way to use extractors is using the magic methods of `Gettext\Translations`:
|
||||
|
||||
```php
|
||||
//Create a Translations instance using a po file
|
||||
$translations = Gettext\Translations::fromPoFile('locales/en.po');
|
||||
|
||||
//Add more messages from other files
|
||||
$translations->addFromPoFile('locales2/en.po');
|
||||
```
|
||||
|
||||
The available extractors are the following:
|
||||
|
||||
Name | Description | Example
|
||||
---- | ----------- | --------
|
||||
**Blade** | Scans a Blade template (For laravel users). | [example](https://github.com/oscarotero/Gettext/blob/master/tests/assets/blade/input.php)
|
||||
**Csv** | Gets the messages from csv. | [example](https://github.com/oscarotero/Gettext/blob/master/tests/assets/po/Csv.csv)
|
||||
**CsvDictionary** | Gets the messages from csv (without plurals and context). | [example](https://github.com/oscarotero/Gettext/blob/master/tests/assets/po/CsvDictionary.csv)
|
||||
**Jed** | Gets the messages from a json compatible with [Jed](http://slexaxton.github.com/Jed/). | [example](https://github.com/oscarotero/Gettext/blob/master/tests/assets/po/Jed.json)
|
||||
**JsCode** | Scans javascript code looking for all gettext functions (the same than PhpCode but for javascript). You can use [the javascript gettext-translator library](https://github.com/oscarotero/gettext-translator) | [example](https://github.com/oscarotero/Gettext/blob/master/tests/assets/jscode/input.js)
|
||||
**Json** | Gets the messages from json compatible with [gettext-translator](https://github.com/oscarotero/gettext-translator). | [example](https://github.com/oscarotero/Gettext/blob/master/tests/assets/po/Json.json)
|
||||
**JsonDictionary** | Gets the messages from a json (without plurals and context). | [example](https://github.com/oscarotero/Gettext/blob/master/tests/assets/po/JsonDictionary.json)
|
||||
**Mo** | Gets the messages from MO. | [example](https://github.com/oscarotero/Gettext/blob/master/tests/assets/po/Mo.mo)
|
||||
**PhpArray** | Gets the messages from a php file that returns an array. | [example](https://github.com/oscarotero/Gettext/blob/master/tests/assets/po/PhpArray.php)
|
||||
**PhpCode** | Scans php code looking for all gettext functions (see `translator_functions.php`). | [example](https://github.com/oscarotero/Gettext/blob/master/tests/assets/phpcode/input.php)
|
||||
**Po** | Gets the messages from PO. | [example](https://github.com/oscarotero/Gettext/blob/master/tests/assets/po/Po.po)
|
||||
**Twig** | To scan a Twig template. | [example](https://github.com/oscarotero/Gettext/blob/master/tests/assets/twig/input.php)
|
||||
**Xliff** | Gets the messages from [xliff (2.0)](http://docs.oasis-open.org/xliff/xliff-core/v2.0/os/xliff-core-v2.0-os.html). | [example](https://github.com/oscarotero/Gettext/blob/master/tests/assets/po/Xliff.xlf)
|
||||
**Yaml** | Gets the messages from yaml. | [example](https://github.com/oscarotero/Gettext/blob/master/tests/assets/po/Yaml.yml)
|
||||
**YamlDictionary** | Gets the messages from a yaml (without plurals and context). | [example](https://github.com/oscarotero/Gettext/blob/master/tests/assets/po/YamlDictionary.yml)
|
||||
**VueJs** | Gets the messages from a VueJs template. | [example](https://github.com/oscarotero/Gettext/blob/master/tests/assets/vuejs/input.vue)
|
||||
|
||||
## Generators
|
||||
|
||||
The generators export a `Gettext\Translations` instance to any format (po, mo, array, etc).
|
||||
|
||||
```php
|
||||
//Save to a file
|
||||
Gettext\Generators\Po::toFile($translations, 'locales/en.po');
|
||||
|
||||
//Return as a string
|
||||
$content = Gettext\Generators\Po::toString($translations);
|
||||
file_put_contents('locales/en.po', $content);
|
||||
```
|
||||
|
||||
Like extractors, the better way to use generators is using the magic methods of `Gettext\Translations`:
|
||||
|
||||
```php
|
||||
//Extract messages from a php code file
|
||||
$translations = Gettext\Translations::fromPhpCodeFile('templates/index.php');
|
||||
|
||||
//Export to a po file
|
||||
$translations->toPoFile('locales/en.po');
|
||||
|
||||
//Export to a po string
|
||||
$content = $translations->toPoString();
|
||||
file_put_contents('locales/en.po', $content);
|
||||
```
|
||||
|
||||
The available generators are the following:
|
||||
|
||||
Name | Description | Example
|
||||
---- | ----------- | --------
|
||||
**Csv** | Exports to csv. | [example](https://github.com/oscarotero/Gettext/blob/master/tests/assets/po/Csv.csv)
|
||||
**CsvDictionary** | Exports to csv (without plurals and context). | [example](https://github.com/oscarotero/Gettext/blob/master/tests/assets/po/CsvDictionary.csv)
|
||||
**Json** | Exports to json, compatible with [gettext-translator](https://github.com/oscarotero/gettext-translator). | [example](https://github.com/oscarotero/Gettext/blob/master/tests/assets/po/Json.json)
|
||||
**JsonDictionary** | Exports to json (without plurals and context). | [example](https://github.com/oscarotero/Gettext/blob/master/tests/assets/po/JsonDictionary.json)
|
||||
**Mo** | Exports to Mo. | [example](https://github.com/oscarotero/Gettext/blob/master/tests/assets/po/Mo.mo)
|
||||
**PhpArray** | Exports to php code that returns an array. | [example](https://github.com/oscarotero/Gettext/blob/master/tests/assets/po/PhpArray.php)
|
||||
**Po** | Exports to Po. | [example](https://github.com/oscarotero/Gettext/blob/master/tests/assets/po/Po.po)
|
||||
**Jed** | Exports to json format compatible with [Jed](http://slexaxton.github.com/Jed/). | [example](https://github.com/oscarotero/Gettext/blob/master/tests/assets/po/Jed.json)
|
||||
**Xliff** | Exports to [xliff (2.0)](http://docs.oasis-open.org/xliff/xliff-core/v2.0/os/xliff-core-v2.0-os.html). | [example](https://github.com/oscarotero/Gettext/blob/master/tests/assets/po/Xliff.xlf)
|
||||
**Yaml** | Exports to yaml. | [example](https://github.com/oscarotero/Gettext/blob/master/tests/assets/po/Yaml.yml)
|
||||
**YamlDictionary** | Exports to yaml (without plurals and context). | [example](https://github.com/oscarotero/Gettext/blob/master/tests/assets/po/YamlDictionary.yml)
|
||||
|
||||
## Translator
|
||||
|
||||
The class `Gettext\Translator` implements the gettext functions in php. Useful if you don't have the native gettext extension for php or want to avoid problems with it. You can load the translations from a php array file or using a `Gettext\Translations` instance:
|
||||
|
||||
```php
|
||||
use Gettext\Translator;
|
||||
|
||||
//Create a new instance of the translator
|
||||
$t = new Translator();
|
||||
|
||||
//Load the translations using any of the following ways:
|
||||
|
||||
// 1. from php files (generated by Gettext\Extractors\PhpArray)
|
||||
$t->loadTranslations('locales/gl.php');
|
||||
|
||||
// 2. using the array directly
|
||||
$array = include 'locales/gl.php';
|
||||
$t->loadTranslations($array);
|
||||
|
||||
// 3. using a Gettext\Translations instance (slower)
|
||||
$translations = Gettext\Translations::fromPoFile('locales/gl.po');
|
||||
$t->loadTranslations($translations);
|
||||
|
||||
//Now you can use it in your templates
|
||||
echo $t->gettext('apple');
|
||||
```
|
||||
|
||||
## GettextTranslator
|
||||
|
||||
The class `Gettext\GettextTranslator` uses the gettext extension. It's useful because combines the performance of using real gettext functions but with the same API than `Translator` class, so you can switch to one or other translator deppending of the environment without change code of your app.
|
||||
|
||||
```php
|
||||
use Gettext\GettextTranslator;
|
||||
|
||||
//Create a new instance
|
||||
$t = new GettextTranslator();
|
||||
|
||||
//It detects the environment variables to set the locale, but you can change it:
|
||||
$t->setLanguage('gl');
|
||||
|
||||
//Load the domains:
|
||||
$t->loadDomain('messages', 'project/Locale');
|
||||
//this means you have the file "project/Locale/gl/LC_MESSAGES/messages.po"
|
||||
|
||||
//Now you can use it in your templates
|
||||
echo $t->gettext('apple');
|
||||
```
|
||||
|
||||
## Global functions
|
||||
|
||||
To ease the use of translations in your php templates, you can use the provided functions:
|
||||
|
||||
```php
|
||||
//Register the translator to use the global functions
|
||||
$t->register();
|
||||
|
||||
echo __('apple'); // it's the same than $t->gettext('apple');
|
||||
```
|
||||
|
||||
You can scan the php files containing these functions and extract the values with the PhpCode extractor:
|
||||
|
||||
```html
|
||||
<!-- index.php -->
|
||||
<html>
|
||||
<body>
|
||||
<?= __('Hello world'); ?>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
|
||||
## Merge translations
|
||||
|
||||
To work with different translations you may want merge them in an unique file. There are two ways to do this:
|
||||
|
||||
The simplest way is adding new translations:
|
||||
|
||||
```php
|
||||
use Gettext\Translations;
|
||||
|
||||
$translations = Translations::fromPoFile('my-file1.po');
|
||||
$translations->addFromPoFile('my-file2.po');
|
||||
```
|
||||
|
||||
A more advanced way is merge two `Translations` instances:
|
||||
|
||||
```php
|
||||
use Gettext\Translations;
|
||||
|
||||
//Create a new Translations instances with our translations.
|
||||
|
||||
$translations1 = Translations::fromPoFile('my-file1.po');
|
||||
$translations2 = Translations::fromPoFile('my-file2.po');
|
||||
|
||||
//Merge one inside other:
|
||||
$translations1->mergeWith($translations2);
|
||||
|
||||
//Now translations1 has all values
|
||||
```
|
||||
|
||||
The second argument of `mergeWith` defines how the merge will be done. Use the `Gettext\Merge` constants to configure the merging:
|
||||
|
||||
Constant | Description
|
||||
--------- | -----------
|
||||
`Merge::ADD` | Adds the translations from `$translations2` that are missing
|
||||
`Merge::REMOVE` | Removes the translations missing in `$translations2`
|
||||
`Merge::HEADERS_ADD` | Adds the headers from `$translations2` that are missing
|
||||
`Merge::HEADERS_REMOVE` | Removes the headers missing in `$translations2`
|
||||
`Merge::HEADERS_OVERRIDE` | Overrides the headers with the values of `$translations2`
|
||||
`Merge::LANGUAGE_OVERRIDE` | Set the language defined in `$translations2`
|
||||
`Merge::DOMAIN_OVERRIDE` | Set the domain defined in `$translations2`
|
||||
`Merge::TRANSLATION_OVERRIDE` | Override the translation and plural translations with the value of `$translation2`
|
||||
`Merge::COMMENTS_OURS` | Use only the comments of `$translation1`
|
||||
`Merge::COMMENTS_THEIRS` | Use only the comments of `$translation2`
|
||||
`Merge::EXTRACTED_COMMENTS_OURS` | Use only the extracted comments of `$translation1`
|
||||
`Merge::EXTRACTED_COMMENTS_THEIRS` | Use only the extracted comments of `$translation2`
|
||||
`Merge::FLAGS_OURS` | Use only the flags of `$translation1`
|
||||
`Merge::FLAGS_THEIRS` | Use only the flags of `$translation2`
|
||||
`Merge::REFERENCES_OURS` | Use only the references of `$translation1`
|
||||
`Merge::REFERENCES_THEIRS` | Use only the references of `$translation2`
|
||||
|
||||
Example:
|
||||
|
||||
```php
|
||||
use Gettext\Translations;
|
||||
use Gettext\Merge;
|
||||
|
||||
//Scan the php code to find the latest gettext translations
|
||||
$phpTranslations = Translations::fromPhpCodeFile('my-templates.php');
|
||||
|
||||
//Get the translations of the code that are stored in a po file
|
||||
$poTranslations = Translations::fromPoFile('locale.po');
|
||||
|
||||
//Merge the translations from the po file using the references from `$phpTranslations`:
|
||||
$translations->mergeWith($poTranslations, Merge::REFERENCES_OURS);
|
||||
|
||||
//Now save a po file with the result
|
||||
$translations->toPoFile('locale.po');
|
||||
```
|
||||
|
||||
Note, if the second argument is not defined, the default value is `Merge::DEFAULTS` that's equivalent to `Merge::ADD | Merge::HEADERS_ADD`.
|
||||
|
||||
## Use from CLI
|
||||
|
||||
There's a Robo task to use this library from the command line interface: https://github.com/oscarotero/GettextRobo
|
||||
|
||||
## Use in the browser
|
||||
|
||||
If you want to use your translations in the browser, there's a javascript translator: https://github.com/oscarotero/gettext-translator
|
||||
|
||||
## Third party packages
|
||||
|
||||
Twig integration:
|
||||
|
||||
* [jaimeperez/twig-configurable-i18n](https://packagist.org/packages/jaimeperez/twig-configurable-i18n)
|
||||
* [cemerson/translator-twig-extension](https://packagist.org/packages/cemerson/translator-twig-extension)
|
||||
|
||||
Framework integration:
|
||||
|
||||
* [Laravel 5](https://packagist.org/packages/eusonlito/laravel-gettext)
|
||||
* [CakePHP 3](https://packagist.org/packages/k1low/po)
|
||||
* [Symfony 2](https://packagist.org/packages/mablae/gettext-bundle)
|
||||
|
||||
[add your package](https://github.com/oscarotero/Gettext/issues/new)
|
||||
|
||||
## Contributors
|
||||
|
||||
Thanks to all [contributors](https://github.com/oscarotero/Gettext/graphs/contributors) specially to [@mlocati](https://github.com/mlocati).
|
||||
|
||||
## Donations
|
||||
|
||||
If this library is useful for you, consider to donate to the author.
|
||||
|
||||
[Buy me a beer :beer:](https://www.paypal.me/oscarotero)
|
||||
|
||||
Thanks in advance!
|
54
inc/gettext/composer.json
Normal file
54
inc/gettext/composer.json
Normal file
|
@ -0,0 +1,54 @@
|
|||
{
|
||||
"name": "gettext/gettext",
|
||||
"type": "library",
|
||||
"description": "PHP gettext manager",
|
||||
"keywords": ["js", "gettext", "i18n", "translation", "po", "mo"],
|
||||
"homepage": "https://github.com/oscarotero/Gettext",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Oscar Otero",
|
||||
"email": "oom@oscarotero.com",
|
||||
"homepage": "http://oscarotero.com",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"support": {
|
||||
"email": "oom@oscarotero.com",
|
||||
"issues": "https://github.com/oscarotero/Gettext/issues"
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.4.0",
|
||||
"gettext/languages": "^2.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"illuminate/view": "*",
|
||||
"twig/twig": "^1.31|^2.0",
|
||||
"twig/extensions": "*",
|
||||
"symfony/yaml": "~2",
|
||||
"phpunit/phpunit": "^4.8|^5.7|^6.5",
|
||||
"squizlabs/php_codesniffer": "^3.0"
|
||||
},
|
||||
"suggest": {
|
||||
"illuminate/view": "Is necessary if you want to use the Blade extractor",
|
||||
"twig/twig": "Is necessary if you want to use the Twig extractor",
|
||||
"twig/extensions": "Is necessary if you want to use the Twig extractor",
|
||||
"symfony/yaml": "Is necessary if you want to use the Yaml extractor/generator"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Gettext\\": "src"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Gettext\\Tests\\": "tests"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"test": [
|
||||
"phpunit",
|
||||
"phpcs"
|
||||
]
|
||||
}
|
||||
}
|
39
inc/gettext/src/BaseTranslator.php
Normal file
39
inc/gettext/src/BaseTranslator.php
Normal file
|
@ -0,0 +1,39 @@
|
|||
<?php
|
||||
|
||||
namespace Gettext;
|
||||
|
||||
abstract class BaseTranslator implements TranslatorInterface
|
||||
{
|
||||
/** @var TranslatorInterface */
|
||||
public static $current;
|
||||
|
||||
/**
|
||||
* @see TranslatorInterface
|
||||
*/
|
||||
public function noop($original)
|
||||
{
|
||||
return $original;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see TranslatorInterface
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
$previous = static::$current;
|
||||
|
||||
static::$current = $this;
|
||||
|
||||
static::includeFunctions();
|
||||
|
||||
return $previous;
|
||||
}
|
||||
|
||||
/**
|
||||
* Include the gettext functions
|
||||
*/
|
||||
public static function includeFunctions()
|
||||
{
|
||||
include_once __DIR__.'/translator_functions.php';
|
||||
}
|
||||
}
|
29
inc/gettext/src/Extractors/Blade.php
Normal file
29
inc/gettext/src/Extractors/Blade.php
Normal file
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
namespace Gettext\Extractors;
|
||||
|
||||
use Gettext\Translations;
|
||||
use Illuminate\Filesystem\Filesystem;
|
||||
use Illuminate\View\Compilers\BladeCompiler;
|
||||
|
||||
/**
|
||||
* Class to get gettext strings from blade.php files returning arrays.
|
||||
*/
|
||||
class Blade extends Extractor implements ExtractorInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function fromString($string, Translations $translations, array $options = [])
|
||||
{
|
||||
if (empty($options['facade'])) {
|
||||
$cachePath = empty($options['cachePath']) ? sys_get_temp_dir() : $options['cachePath'];
|
||||
$bladeCompiler = new BladeCompiler(new Filesystem(), $cachePath);
|
||||
$string = $bladeCompiler->compileString($string);
|
||||
} else {
|
||||
$string = $options['facade']::compileString($string);
|
||||
}
|
||||
|
||||
PhpCode::fromString($string, $translations, $options);
|
||||
}
|
||||
}
|
53
inc/gettext/src/Extractors/Csv.php
Normal file
53
inc/gettext/src/Extractors/Csv.php
Normal file
|
@ -0,0 +1,53 @@
|
|||
<?php
|
||||
|
||||
namespace Gettext\Extractors;
|
||||
|
||||
use Gettext\Translations;
|
||||
use Gettext\Utils\HeadersExtractorTrait;
|
||||
use Gettext\Utils\CsvTrait;
|
||||
|
||||
/**
|
||||
* Class to get gettext strings from csv.
|
||||
*/
|
||||
class Csv extends Extractor implements ExtractorInterface
|
||||
{
|
||||
use HeadersExtractorTrait;
|
||||
use CsvTrait;
|
||||
|
||||
public static $options = [
|
||||
'delimiter' => ",",
|
||||
'enclosure' => '"',
|
||||
'escape_char' => "\\"
|
||||
];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function fromString($string, Translations $translations, array $options = [])
|
||||
{
|
||||
$options += static::$options;
|
||||
$handle = fopen('php://memory', 'w');
|
||||
|
||||
fputs($handle, $string);
|
||||
rewind($handle);
|
||||
|
||||
while ($row = static::fgetcsv($handle, $options)) {
|
||||
$context = array_shift($row);
|
||||
$original = array_shift($row);
|
||||
|
||||
if ($context === '' && $original === '') {
|
||||
static::extractHeaders(array_shift($row), $translations);
|
||||
continue;
|
||||
}
|
||||
|
||||
$translation = $translations->insert($context, $original);
|
||||
|
||||
if (!empty($row)) {
|
||||
$translation->setTranslation(array_shift($row));
|
||||
$translation->setPluralTranslations($row);
|
||||
}
|
||||
}
|
||||
|
||||
fclose($handle);
|
||||
}
|
||||
}
|
47
inc/gettext/src/Extractors/CsvDictionary.php
Normal file
47
inc/gettext/src/Extractors/CsvDictionary.php
Normal file
|
@ -0,0 +1,47 @@
|
|||
<?php
|
||||
|
||||
namespace Gettext\Extractors;
|
||||
|
||||
use Gettext\Translations;
|
||||
use Gettext\Utils\HeadersExtractorTrait;
|
||||
use Gettext\Utils\CsvTrait;
|
||||
|
||||
/**
|
||||
* Class to get gettext strings from csv.
|
||||
*/
|
||||
class CsvDictionary extends Extractor implements ExtractorInterface
|
||||
{
|
||||
use HeadersExtractorTrait;
|
||||
use CsvTrait;
|
||||
|
||||
public static $options = [
|
||||
'delimiter' => ",",
|
||||
'enclosure' => '"',
|
||||
'escape_char' => "\\"
|
||||
];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function fromString($string, Translations $translations, array $options = [])
|
||||
{
|
||||
$options += static::$options;
|
||||
$handle = fopen('php://memory', 'w');
|
||||
|
||||
fputs($handle, $string);
|
||||
rewind($handle);
|
||||
|
||||
while ($row = static::fgetcsv($handle, $options)) {
|
||||
list($original, $translation) = $row + ['', ''];
|
||||
|
||||
if ($original === '') {
|
||||
static::extractHeaders($translation, $translations);
|
||||
continue;
|
||||
}
|
||||
|
||||
$translations->insert(null, $original)->setTranslation($translation);
|
||||
}
|
||||
|
||||
fclose($handle);
|
||||
}
|
||||
}
|
80
inc/gettext/src/Extractors/Extractor.php
Normal file
80
inc/gettext/src/Extractors/Extractor.php
Normal file
|
@ -0,0 +1,80 @@
|
|||
<?php
|
||||
|
||||
namespace Gettext\Extractors;
|
||||
|
||||
use Exception;
|
||||
use InvalidArgumentException;
|
||||
use Gettext\Translations;
|
||||
|
||||
abstract class Extractor implements ExtractorInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function fromFile($file, Translations $translations, array $options = [])
|
||||
{
|
||||
foreach (static::getFiles($file) as $file) {
|
||||
$options['file'] = $file;
|
||||
static::fromString(static::readFile($file), $translations, $options);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks and returns all files.
|
||||
*
|
||||
* @param string|array $file The file/s
|
||||
*
|
||||
* @return array The file paths
|
||||
*/
|
||||
protected static function getFiles($file)
|
||||
{
|
||||
if (empty($file)) {
|
||||
throw new InvalidArgumentException('There is not any file defined');
|
||||
}
|
||||
|
||||
if (is_string($file)) {
|
||||
if (!is_file($file)) {
|
||||
throw new InvalidArgumentException("'$file' is not a valid file");
|
||||
}
|
||||
|
||||
if (!is_readable($file)) {
|
||||
throw new InvalidArgumentException("'$file' is not a readable file");
|
||||
}
|
||||
|
||||
return [$file];
|
||||
}
|
||||
|
||||
if (is_array($file)) {
|
||||
$files = [];
|
||||
|
||||
foreach ($file as $f) {
|
||||
$files = array_merge($files, static::getFiles($f));
|
||||
}
|
||||
|
||||
return $files;
|
||||
}
|
||||
|
||||
throw new InvalidArgumentException('The first argument must be string or array');
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads and returns the content of a file.
|
||||
*
|
||||
* @param string $file
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected static function readFile($file)
|
||||
{
|
||||
$length = filesize($file);
|
||||
|
||||
if (!($fd = fopen($file, 'rb'))) {
|
||||
throw new Exception("Cannot read the file '$file', probably permissions");
|
||||
}
|
||||
|
||||
$content = $length ? fread($fd, $length) : '';
|
||||
fclose($fd);
|
||||
|
||||
return $content;
|
||||
}
|
||||
}
|
26
inc/gettext/src/Extractors/ExtractorInterface.php
Normal file
26
inc/gettext/src/Extractors/ExtractorInterface.php
Normal file
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
|
||||
namespace Gettext\Extractors;
|
||||
|
||||
use Gettext\Translations;
|
||||
|
||||
interface ExtractorInterface
|
||||
{
|
||||
/**
|
||||
* Extract the translations from a file.
|
||||
*
|
||||
* @param array|string $file A path of a file or files
|
||||
* @param Translations $translations The translations instance to append the new translations.
|
||||
* @param array $options
|
||||
*/
|
||||
public static function fromFile($file, Translations $translations, array $options = []);
|
||||
|
||||
/**
|
||||
* Parses a string and append the translations found in the Translations instance.
|
||||
*
|
||||
* @param string $string
|
||||
* @param Translations $translations
|
||||
* @param array $options
|
||||
*/
|
||||
public static function fromString($string, Translations $translations, array $options = []);
|
||||
}
|
28
inc/gettext/src/Extractors/ExtractorMultiInterface.php
Normal file
28
inc/gettext/src/Extractors/ExtractorMultiInterface.php
Normal file
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
namespace Gettext\Extractors;
|
||||
|
||||
use Gettext\Translations;
|
||||
|
||||
interface ExtractorMultiInterface
|
||||
{
|
||||
/**
|
||||
* Parses a string and append the translations found in the Translations instance.
|
||||
* Allows scanning for multiple domains at a time (each Translation has to have a different domain)
|
||||
*
|
||||
* @param string $string
|
||||
* @param Translations[] $translations
|
||||
* @param array $options
|
||||
*/
|
||||
public static function fromStringMultiple($string, array $translations, array $options = []);
|
||||
|
||||
/**
|
||||
* Parses a string and append the translations found in the Translations instance.
|
||||
* Allows scanning for multiple domains at a time (each Translation has to have a different domain)
|
||||
*
|
||||
* @param $file
|
||||
* @param Translations[] $translations
|
||||
* @param array $options
|
||||
*/
|
||||
public static function fromFileMultiple($file, array $translations, array $options = []);
|
||||
}
|
55
inc/gettext/src/Extractors/Jed.php
Normal file
55
inc/gettext/src/Extractors/Jed.php
Normal file
|
@ -0,0 +1,55 @@
|
|||
<?php
|
||||
|
||||
namespace Gettext\Extractors;
|
||||
|
||||
use Gettext\Translations;
|
||||
|
||||
/**
|
||||
* Class to get gettext strings from json files.
|
||||
*/
|
||||
class Jed extends Extractor implements ExtractorInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function fromString($string, Translations $translations, array $options = [])
|
||||
{
|
||||
static::extract(json_decode($string, true), $translations);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle an array of translations and append to the Translations instance.
|
||||
*
|
||||
* @param array $content
|
||||
* @param Translations $translations
|
||||
*/
|
||||
public static function extract(array $content, Translations $translations)
|
||||
{
|
||||
$messages = current($content);
|
||||
$headers = isset($messages['']) ? $messages[''] : null;
|
||||
unset($messages['']);
|
||||
|
||||
if (!empty |