Subversion-Projekte lars-tiefland.laravel_shop

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
148 lars 1
<?php
2
 
3
/*
4
 * This file is part of the Symfony package.
5
 *
6
 * (c) Fabien Potencier <fabien@symfony.com>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
 
12
namespace Symfony\Component\Translation\Loader;
13
 
14
/**
15
 * @copyright Copyright (c) 2010, Union of RAD https://github.com/UnionOfRAD/lithium
16
 * @copyright Copyright (c) 2012, Clemens Tolboom
17
 */
18
class PoFileLoader extends FileLoader
19
{
20
    /**
21
     * Parses portable object (PO) format.
22
     *
23
     * From https://www.gnu.org/software/gettext/manual/gettext.html#PO-Files
24
     * we should be able to parse files having:
25
     *
26
     * white-space
27
     * #  translator-comments
28
     * #. extracted-comments
29
     * #: reference...
30
     * #, flag...
31
     * #| msgid previous-untranslated-string
32
     * msgid untranslated-string
33
     * msgstr translated-string
34
     *
35
     * extra or different lines are:
36
     *
37
     * #| msgctxt previous-context
38
     * #| msgid previous-untranslated-string
39
     * msgctxt context
40
     *
41
     * #| msgid previous-untranslated-string-singular
42
     * #| msgid_plural previous-untranslated-string-plural
43
     * msgid untranslated-string-singular
44
     * msgid_plural untranslated-string-plural
45
     * msgstr[0] translated-string-case-0
46
     * ...
47
     * msgstr[N] translated-string-case-n
48
     *
49
     * The definition states:
50
     * - white-space and comments are optional.
51
     * - msgid "" that an empty singleline defines a header.
52
     *
53
     * This parser sacrifices some features of the reference implementation the
54
     * differences to that implementation are as follows.
55
     * - No support for comments spanning multiple lines.
56
     * - Translator and extracted comments are treated as being the same type.
57
     * - Message IDs are allowed to have other encodings as just US-ASCII.
58
     *
59
     * Items with an empty id are ignored.
60
     */
61
    protected function loadResource(string $resource): array
62
    {
63
        $stream = fopen($resource, 'r');
64
 
65
        $defaults = [
66
            'ids' => [],
67
            'translated' => null,
68
        ];
69
 
70
        $messages = [];
71
        $item = $defaults;
72
        $flags = [];
73
 
74
        while ($line = fgets($stream)) {
75
            $line = trim($line);
76
 
77
            if ('' === $line) {
78
                // Whitespace indicated current item is done
79
                if (!\in_array('fuzzy', $flags)) {
80
                    $this->addMessage($messages, $item);
81
                }
82
                $item = $defaults;
83
                $flags = [];
84
            } elseif (str_starts_with($line, '#,')) {
85
                $flags = array_map('trim', explode(',', substr($line, 2)));
86
            } elseif (str_starts_with($line, 'msgid "')) {
87
                // We start a new msg so save previous
88
                // TODO: this fails when comments or contexts are added
89
                $this->addMessage($messages, $item);
90
                $item = $defaults;
91
                $item['ids']['singular'] = substr($line, 7, -1);
92
            } elseif (str_starts_with($line, 'msgstr "')) {
93
                $item['translated'] = substr($line, 8, -1);
94
            } elseif ('"' === $line[0]) {
95
                $continues = isset($item['translated']) ? 'translated' : 'ids';
96
 
97
                if (\is_array($item[$continues])) {
98
                    end($item[$continues]);
99
                    $item[$continues][key($item[$continues])] .= substr($line, 1, -1);
100
                } else {
101
                    $item[$continues] .= substr($line, 1, -1);
102
                }
103
            } elseif (str_starts_with($line, 'msgid_plural "')) {
104
                $item['ids']['plural'] = substr($line, 14, -1);
105
            } elseif (str_starts_with($line, 'msgstr[')) {
106
                $size = strpos($line, ']');
107
                $item['translated'][(int) substr($line, 7, 1)] = substr($line, $size + 3, -1);
108
            }
109
        }
110
        // save last item
111
        if (!\in_array('fuzzy', $flags)) {
112
            $this->addMessage($messages, $item);
113
        }
114
        fclose($stream);
115
 
116
        return $messages;
117
    }
118
 
119
    /**
120
     * Save a translation item to the messages.
121
     *
122
     * A .po file could contain by error missing plural indexes. We need to
123
     * fix these before saving them.
124
     */
125
    private function addMessage(array &$messages, array $item)
126
    {
127
        if (!empty($item['ids']['singular'])) {
128
            $id = stripcslashes($item['ids']['singular']);
129
            if (isset($item['ids']['plural'])) {
130
                $id .= '|'.stripcslashes($item['ids']['plural']);
131
            }
132
 
133
            $translated = (array) $item['translated'];
134
            // PO are by definition indexed so sort by index.
135
            ksort($translated);
136
            // Make sure every index is filled.
137
            end($translated);
138
            $count = key($translated);
139
            // Fill missing spots with '-'.
140
            $empties = array_fill(0, $count + 1, '-');
141
            $translated += $empties;
142
            ksort($translated);
143
 
144
            $messages[$id] = stripcslashes(implode('|', $translated));
145
        }
146
    }
147
}