Lines 96.42% 81 / 84
Methods 77.77% 7 / 9
Classes 0.00% 0 / 1
Covered by tests of size
Name Lines Methods CRAP
 getProviderName 100.00% 1 / 1 100.00% 1 / 1 1
 doTranslate 100.00% 2 / 2 100.00% 1 / 1 1
 doTranslateBatch 92.00% 23 / 25 0.00% 0 / 1 4.01
 translateBatch 66.66% 2 / 3 0.00% 0 / 1 2.15
 supportsLanguagePair 100.00% 1 / 1 100.00% 1 / 1 1
 getSupportedLanguages 100.00% 43 / 43 100.00% 1 / 1 1
 mapLanguageCode 100.00% 1 / 1 100.00% 1 / 1 1
 [phpMyFAQ\Translation\AbstractTranslationProvider] __construct 100.00% 1 / 1 100.00% 1 / 1 1
 [phpMyFAQ\Translation\AbstractTranslationProvider] translate 100.00% 7 / 7 100.00% 1 / 1 3
30class AzureTranslationProvider extends AbstractTranslationProvider
31{
32    private const string API_URL = 'https://api.cognitive.microsofttranslator.com/translate?api-version=3.0';
33
34    /**
35     * @inheritDoc
36     */
37    public function getProviderName(): string
38    {
39        return 'Azure Translator';
40    }
41
42    /**
43     * @inheritDoc
44     */
45    protected function doTranslate(string $text, string $sourceLang, string $targetLang): string
46    {
47        $results = $this->doTranslateBatch([$text], $sourceLang, $targetLang);
48        return $results[0] ?? '';
49    }
50
51    /**
52     * @inheritDoc
53     */
54    protected function doTranslateBatch(array $texts, string $sourceLang, string $targetLang): array
55    {
56        $apiKey = $this->configuration->get('translation.azureKey');
57        $region = $this->configuration->get('translation.azureRegion');
58
59        if ((string) $apiKey === '') {
60            throw new ApiException('Azure Translator API key not configured');
61        }
62
63        if ((string) $region === '') {
64            throw new ApiException('Azure Translator region not configured');
65        }
66
67        $url =
68            self::API_URL
69            . '&from='
70            . $this->mapLanguageCode($sourceLang)
71            . '&to='
72            . $this->mapLanguageCode($targetLang);
73
74        $body = array_map(static fn($text) => ['text' => $text], $texts);
75
76        try {
77            $response = $this->httpClient->request('POST', $url, [
78                'headers' => [
79                    'Ocp-Apim-Subscription-Key' => $apiKey,
80                    'Ocp-Apim-Subscription-Region' => $region,
81                    'Content-Type' => 'application/json',
82                ],
83                'json' => $body,
84            ]);
85
86            $data = $response->toArray();
87            return array_map(static fn($item): string => (string) ($item['translations'][0]['text'] ?? ''), $data);
88        } catch (\Exception $e) {
89            throw new ApiException('Azure Translator API error: ' . $e->getMessage());
90        }
91    }
92
93    /**
94     * @inheritDoc
95     */
96    public function translateBatch(
97        array $texts,
98        string $sourceLang,
99        string $targetLang,
100        bool $preserveHtml = false,
101    ): array {
102        if ($preserveHtml) {
103            // Process each text individually with HTML preservation
104            return array_map(fn($text) => $this->translate($text, $sourceLang, $targetLang, true), $texts);
105        }
106
107        return $this->doTranslateBatch($texts, $sourceLang, $targetLang);
108    }
109
110    /**
111     * @inheritDoc
112     */
113    public function supportsLanguagePair(string $sourceLang, string $targetLang): bool
114    {
115        // Azure Translator supports most language pairs
116        return true;
117    }
118
119    /**
120     * @inheritDoc
121     */
122    public function getSupportedLanguages(): array
123    {
124        // Common languages supported by Azure Translator
125        return [
126            'ar',
127            'bn',
128            'bs',
129            'cs',
130            'cy',
131            'da',
132            'de',
133            'el',
134            'en',
135            'es',
136            'eu',
137            'fa',
138            'fi',
139            'fr',
140            'he',
141            'hi',
142            'hu',
143            'id',
144            'it',
145            'ja',
146            'ko',
147            'lt',
148            'lv',
149            'mn',
150            'ms',
151            'nb',
152            'nl',
153            'pl',
154            'pt',
155            'ro',
156            'ru',
157            'sk',
158            'sl',
159            'sr',
160            'sv',
161            'th',
162            'tr',
163            'uk',
164            'ur',
165            'vi',
166            'zh',
167        ];
168    }
169
170    /**
171     * @inheritDoc
172     */
173    protected function mapLanguageCode(string $pmfLangCode): string
174    {
175        // Azure uses standard ISO 639-1
176        return $pmfLangCode;
177    }
178}

Inherited from phpMyFAQ\Translation\AbstractTranslationProvider

41    public function __construct(
42        protected readonly Configuration $configuration,
43        protected readonly HttpClientInterface $httpClient,
44    ) {
45        $this->htmlPreserver = new HtmlPreserver();
46    }
58    public function translate(string $text, string $sourceLang, string $targetLang, bool $preserveHtml = false): string
59    {
60        if ($text === '') {
61            return '';
62        }
63
64        if ($preserveHtml) {
65            [$textWithPlaceholders, $htmlMap] = $this->htmlPreserver->replaceTags($text);
66            $translated = $this->doTranslate($textWithPlaceholders, $sourceLang, $targetLang);
67            return $this->htmlPreserver->restoreTags($translated, $htmlMap);
68        }
69
70        return $this->doTranslate($text, $sourceLang, $targetLang);
71    }