Completed
Push — master ( 90072e...c81959 )
by Daniel
11:23
created

ModuleYamlLoader::getReader()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 0
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace SilverStripe\i18n\Messages\Symfony;
4
5
use SilverStripe\Core\Config\Configurable;
6
use SilverStripe\Dev\Debug;
7
use SilverStripe\i18n\i18n;
8
use SilverStripe\i18n\Messages\Reader;
9
use Symfony\Component\Translation\Loader\ArrayLoader;
10
use Symfony\Component\Translation\PluralizationRules;
11
12
/**
13
 * Loads yaml localisations across all modules simultaneously.
14
 * Note: This will also convert rails yml plurals into symfony standard format.
15
 * Acts as a YamlFileLoader, but across a list of modules
16
 */
17
class ModuleYamlLoader extends ArrayLoader
18
{
19
    /**
20
     * Message reader
21
     *
22
     * @var Reader
23
     */
24
    protected $reader = null;
25
26
    public function load($resource, $locale, $domain = 'messages')
27
    {
28
        $messages = [];
29
        foreach ($resource as $path) {
30
            // Note: already-loaded messages have higher priority
31
            $messages = array_merge(
32
                $this->loadMessages($path, $locale),
33
                $messages
34
            );
35
        }
36
        ksort($messages);
37
        $catalog = parent::load($messages, $locale, $domain);
38
39
        // Ensure this catalog is invalidated on flush
40
        $catalog->addResource(new FlushInvalidatedResource());
41
        return $catalog;
42
    }
43
44
    /**
45
     * @return Reader
46
     */
47
    public function getReader()
48
    {
49
        return $this->reader;
50
    }
51
52
    /**
53
     * @param Reader $reader
54
     * @return $this
55
     */
56
    public function setReader(Reader $reader)
57
    {
58
        $this->reader = $reader;
59
        return $this;
60
    }
61
62
63
    /**
64
     * Load messages
65
     *
66
     * @param string $path
67
     * @param string $locale
68
     * @return array
69
     */
70
    protected function loadMessages($path, $locale)
71
    {
72
        $filePath = $path . $locale . '.yml';
73
        $messages = $this->getReader()->read($locale, $filePath);
74
        return $this->normaliseMessages($messages, $locale);
75
    }
76
77
    /**
78
     * Normalises plurals in messages from rails-yaml format to symfony.
79
     *
80
     * @param array $messages List of messages
81
     * @param string $locale
82
     * @return array Normalised messages
83
     */
84
    protected function normaliseMessages($messages, $locale)
85
    {
86
        foreach ($messages as $key => $value) {
87
            if (is_array($value)) {
88
                $messages[$key] = $this->normalisePlurals($key, $value, $locale);
89
            }
90
        }
91
        return $messages;
92
    }
93
94
    /**
95
     * Normalise rails-yaml plurals into pipe-separated rules
96
     *
97
     * @link http://www.unicode.org/cldr/charts/latest/supplemental/language_plural_rules.html
98
     * @link http://guides.rubyonrails.org/i18n.html#pluralization
99
     * @link http://symfony.com/doc/current/components/translation/usage.html#component-translation-pluralization
100
     *
101
     * @param string $key
102
     * @param array $map
103
     * @param string $locale
104
     * @return string
105
     */
106
    protected function normalisePlurals($key, $map, $locale)
107
    {
108
        $parts = [];
109
        foreach (i18n::config()->get('plurals') as $form) {
110
            if (isset($map[$form])) {
111
                $parts[] = $map[$form];
112
            }
113
        }
114
        // Non-associative plural, just keep in same order
115
        if (empty($parts)) {
116
            return $parts = $map;
117
        }
118
119
        // Warn if mismatched plural forms
120
        if (count($map) !== count($parts)) {
121
            trigger_error("Plural form {$locale}.{$key} has invalid plural keys", E_USER_WARNING);
122
        }
123
124
        return implode('|', $parts);
125
    }
126
}
127