• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

FluidTYPO3 / vhs / 30001290505

23 Jul 2026 10:57AM UTC coverage: 70.309% (-1.7%) from 72.022%
30001290505

push

github

NamelessCoder
[TER] 8.0.0

4819 of 6854 relevant lines covered (70.31%)

6.54 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

86.54
/Classes/ViewHelpers/Resource/LanguageViewHelper.php
1
<?php
2
namespace FluidTYPO3\Vhs\ViewHelpers\Resource;
3

4
/*
5
 * This file is part of the FluidTYPO3/Vhs project under GPLv2 or later.
6
 *
7
 * For the full copyright and license information, please read the
8
 * LICENSE.md file that was distributed with this source code.
9
 */
10

11
use FluidTYPO3\Vhs\Core\ViewHelper\AbstractViewHelper;
12
use FluidTYPO3\Vhs\Proxy\LocalizationFactoryProxy;
13
use FluidTYPO3\Vhs\Traits\TemplateVariableViewHelperTrait;
14
use FluidTYPO3\Vhs\Utility\ContextUtility;
15
use FluidTYPO3\Vhs\Utility\RequestResolver;
16
use Psr\Http\Message\ServerRequestInterface;
17
use TYPO3\CMS\Core\Localization\Locale;
18
use TYPO3\CMS\Core\Site\Entity\SiteLanguage;
19
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
20
use TYPO3\CMS\Core\Utility\GeneralUtility;
21
use TYPO3\CMS\Lang\LanguageService;
22

23
/**
24
 * Resource: Language
25
 *
26
 * Reads a certain language file with returning not just one single label,
27
 * but all the translated labels.
28
 *
29
 * ### Examples
30
 *
31
 * ```
32
 * <!-- Tag usage for force getting labels in a specific language (different to current is possible too) -->
33
 * <v:resource.language extensionName="myext" path="Path/To/Locallang.xlf" languageKey="en"/>
34
 * ```
35
 *
36
 * ```
37
 * <!-- Tag usage for getting labels of current language -->
38
 * <v:resource.language extensionName="myext" path="Path/To/Locallang.xlf"/>
39
 * ```
40
 */
41
class LanguageViewHelper extends AbstractViewHelper
42
{
43
    use TemplateVariableViewHelperTrait;
44

45
    private const string LOCALLANG_DEFAULT = 'locallang.xlf';
46

47
    /**
48
     * @var boolean
49
     */
50
    protected $escapeOutput = false;
51

52
    public function initializeArguments(): void
53
    {
54
        $this->registerAsArgument();
3✔
55
        $this->registerArgument('extensionName', 'string', 'Name of the extension');
3✔
56
        $this->registerArgument(
3✔
57
            'path',
3✔
58
            'string',
3✔
59
            'Absolute or relative path to the locallang file',
3✔
60
            false,
3✔
61
            self::LOCALLANG_DEFAULT
3✔
62
        );
3✔
63
        $this->registerArgument(
3✔
64
            'languageKey',
3✔
65
            'string',
3✔
66
            'Key for getting translation of a different than current initialized language'
3✔
67
        );
3✔
68
    }
69

70
    public function render(): mixed
71
    {
72
        $path = $this->getResolvedPath();
3✔
73
        $languageKey = $this->getLanguageKey();
3✔
74
        /** @var LocalizationFactoryProxy $languageFactory */
75
        $languageFactory = GeneralUtility::makeInstance(LocalizationFactoryProxy::class);
3✔
76
        $locallang = (array) $languageFactory->getParsedData($path, $languageKey);
3✔
77
        $labels = $this->getLabelsByLanguageKey($locallang, $languageKey);
3✔
78
        $labels = $this->getLabelsFromTarget($labels);
3✔
79
        return $this->renderChildrenWithVariableOrReturnInput($labels);
3✔
80
    }
81

82
    /**
83
     * Gets the extension name from defined argument or
84
     * tries to resolve it from the controller context if not set.
85
     */
86
    protected function getResolvedExtensionName(): ?string
87
    {
88
        /** @var string|null $extensionName */
89
        $extensionName = $this->arguments['extensionName'];
3✔
90

91
        return $extensionName
3✔
92
            ?? RequestResolver::resolveControllerExtensionNameFromRenderingContext($this->renderingContext);
3✔
93
    }
94

95
    /**
96
     * Gets the resolved file path with trying to resolve relative paths even if no
97
     * extension key is defined.
98
     */
99
    protected function getResolvedPath(): string
100
    {
101
        /** @var string $path */
102
        $path = $this->arguments['path'];
3✔
103
        $absoluteFileName = GeneralUtility::getFileAbsFileName($path);
3✔
104

105
        if (!file_exists($absoluteFileName) && ($extensionName = $this->getResolvedExtensionName())) {
3✔
106
            $extensionKey = GeneralUtility::camelCaseToLowerCaseUnderscored($extensionName);
3✔
107
            $absoluteFileName = ExtensionManagementUtility::extPath($extensionKey, $path);
3✔
108
        }
109

110
        return $absoluteFileName;
3✔
111
    }
112

113
    /**
114
     * Gets the translated labels by a specific language key
115
     * or fallback to 'default'.
116
     */
117
    protected function getLabelsByLanguageKey(array $locallang, string $languageKey): array
118
    {
119
        $labels = [];
3✔
120

121
        if (!empty($locallang[$languageKey])) {
3✔
122
            $labels = $locallang[$languageKey];
×
123
        } elseif (!empty($locallang['default'])) {
3✔
124
            $labels = $locallang['default'];
×
125
        }
126

127
        return $labels;
3✔
128
    }
129

130
    /**
131
     * Simplify label array with just taking the value from target.
132
     */
133
    protected function getLabelsFromTarget(array $labels): array
134
    {
135
        foreach ($labels as $labelKey => $label) {
3✔
136
            $labels[$labelKey] = $label[0]['target'];
×
137
        }
138

139
        return $labels;
3✔
140
    }
141

142
    /**
143
     * Gets the language key from arguments or from current
144
     * initialized language if argument is not defined.
145
     */
146
    protected function getLanguageKey(): string
147
    {
148
        /** @var string|null $languageKey */
149
        $languageKey = $this->arguments['languageKey'];
3✔
150
        return $languageKey ?? $this->getInitializedLanguage();
3✔
151
    }
152

153
    /**
154
     * Gets the key of current initialized language
155
     * or fallback to 'default'.
156
     */
157
    protected function getInitializedLanguage(): string
158
    {
159
        $language = 'default';
3✔
160

161
        if (ContextUtility::isFrontend()) {
3✔
162
            /** @var ServerRequestInterface $request */
163
            $request = $GLOBALS['TYPO3_REQUEST'];
3✔
164
            /** @var SiteLanguage $language */
165
            $language = $request->getAttribute('language');
3✔
166
            /** @var Locale|string $locale */
167
            $locale = $language->getLocale();
3✔
168
            if (is_string($locale)) {
3✔
169
                return $locale;
×
170
            }
171
            return $locale->getLanguageCode();
3✔
172
        } elseif ($GLOBALS['LANG'] instanceof LanguageService) {
×
173
            $language = $GLOBALS['LANG']->lang;
×
174
        }
175

176
        return (string) $language;
×
177
    }
178
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc