phpffcms/ffcms-core

View on GitHub
src/I18n/Translate.php

Summary

Maintainability
A
1 hr
Test Coverage
<?php

namespace Ffcms\Core\I18n;

use Ffcms\Core\App;
use Ffcms\Core\Helper\FileSystem\Directory;
use Ffcms\Core\Helper\FileSystem\File;
use Ffcms\Core\Helper\FileSystem\Normalize;
use Ffcms\Core\Helper\Serialize;
use Ffcms\Core\Helper\Type\Any;
use Ffcms\Core\Helper\Type\Arr;
use Ffcms\Core\Helper\Type\Obj;
use Ffcms\Core\Helper\Type\Str;

/**
 * Class Translate. Provide methods to work with internalization data in ffcms.
 * @package Ffcms\Core\I18n
 */
class Translate
{
    protected $cached = [];
    protected $indexes = [];

    /**
     * Translate constructor. Load default translations.
     */
    public function __construct()
    {
        if (App::$Request->getLanguage() !== App::$Properties->get('baseLanguage')) {
            $this->cached = $this->load('Default');
            $this->indexes[] = 'Default';
        }
    }


    /**
     * Get internalization of current text from i18n
     * @param string $index
     * @param string $text
     * @param array|null $params
     * @return string
     */
    public function get(?string $index, string $text, ?array $params = null)
    {
        if (App::$Request->getLanguage() !== App::$Properties->get('baseLanguage')) {
            if ($index && !Arr::in($index, $this->indexes)) {
                $this->cached = Arr::merge($this->cached, $this->load($index));
                $this->indexes[] = $index;
            }

            if ($this->cached && Any::isStr($text) && isset($this->cached[$text])) {
                $text = $this->cached[$text];
            }
        }

        if (Any::isArray($params) && count($params) > 0) {
            foreach ($params as $var => $value) {
                $text = Str::replace('%' . $var . '%', $value, $text);
            }
        }
        return $text;
    }

    /**
     * Get internalization based on called controller
     * @param string $text
     * @param array $params
     * @return string
     */
    public function translate(string $text, array $params = null)
    {
        $index = null;
        $namespace = 'Apps\Controller\\' . env_name . '\\';
        foreach (@debug_backtrace() as $caller) {
            if (isset($caller['class']) && Str::startsWith($namespace, $caller['class'])) {
                $index = Str::sub((string)$caller['class'], Str::length($namespace));
            }
        }
        return $this->get($index, $text, $params);
    }

    /**
     * Load locale file from local storage
     * @param string $index
     * @return array|null
     */
    protected function load(string $index): ?array
    {
        $file = root . '/I18n/' . env_name . '/' . App::$Request->getLanguage() . '/' . $index . '.php';
        if (!File::exist($file)) {
            return [];
        }

        return require($file);
    }

    /**
     * Append translation data from exist full path
     * @param string $path
     * @param bool $override
     * @return bool
     */
    public function append($path): bool
    {
        $path = Normalize::diskFullPath($path);
        // check if file exist
        if (!File::exist($path)) {
            return false;
        }

        // load file translations
        $addTranslation = require($path);
        if (!Any::isArray($addTranslation)) {
            return false;
        }

        $this->cached = Arr::merge($this->cached, $addTranslation);

        return true;
    }

    /**
     * Get available languages in the filesystem
     * @return array
     */
    public function getAvailableLangs(): array
    {
        $langs = ['en'];
        $scan = Directory::scan(root . '/I18n/' . env_name . '/', GLOB_ONLYDIR, true);
        foreach ($scan as $row) {
            $langs[] = trim($row, '/');
        }
        return $langs;
    }

    /**
     * Get locale data from input array or serialized string
     * @param array|string $input
     * @param string|null $lang
     * @param string|null $default
     * @return string|null
     */
    public function getLocaleText($input, ?string $lang = null, ?string $default = null): ?string
    {
        // define language if empty
        if ($lang === null) {
            $lang = App::$Request->getLanguage();
        }
        // unserialize from string to array
        if (Any::isStr($input)) {
            $input = Serialize::decode($input);
        }

        if (Any::isArray($input) && array_key_exists($lang, $input)) {
            return $input[$lang];
        }

        return $default;
    }
}