lochmueller / language_detection

🌎 Coolest TYPO3 language detection 🌎
14 stars 6 forks source link

Is there a way to follow locales like de_at, de_ch #26

Closed ako-3004 closed 2 years ago

ako-3004 commented 2 years ago

I use version 3.0.0 on TYPO3 10.4.26 Website default language is english. Foreign language 1 is german.

Browser language I tested with de_de and en_us. This works fine.

Browser language but on de_at, de_ch and more redirects to english which is not correct in my opinion. Is this configurable?

lochmueller commented 2 years ago

Hey @ako-3004 this is the behavior of the DefaultNegotation: https://github.com/lochmueller/language_detection/blob/main/Classes/Negotiation/DefaultNegotiation.php#L26

In the default, we first iterate the $userLanguages and check this against the website Languages. If you switch this foreach's you will get your desired behavior.

Currently, there is no configuration for this. You could add an own NegotationEventListener to handle this and overwrite the default. What kind of configuration do you expect? Additional Locales in the Languages configuration to add "de_AT", "de_CH" to the "de_de" main languages? Or a option to change the Loop order in the foreach?

Reagrds, Tim

ako-3004 commented 2 years ago

Thanks Tim, I will try this with the NegotationEventListener and hopefully this is some php stuff I will understand :) I expected that any browser setting with "de_??" would match the system language "de". I mean the old extension rlmp_language_detection extracted the first 2 characters and used them for language detection. If I succeed I will post the solution here.

Thanks, Alex

lochmueller commented 2 years ago

Hey @ako-3004 It is always based on the use-case. Your default language in TYPO3 should be a locale, so it is "de-DE". But keep in mind, that the default negotiation also match against "getTwoLetterIsoCode" and a regular Browser configuration for e.g. German send "de,de_DE" as languages. So there should be a "de" -> "de" Match. But you have to debug your case.

You can send me the "accept-language" header of your request and the Locale & TwoLetterIsoCode of ALL your languages + your expectation. Than I can put this into the test suite and we can discuss the "best result".

ako-3004 commented 2 years ago

I continued working on this. The solution that helps me out is simple and is easy to explain.

My problem with the language detection is best described with following situation: Set Firefox language setting just to "Deutsch (Österreich) [de-at]". Then the request header is: "Accept-Language de-AT". This will not match any of the TYPO3 languages (neither "de-DE", "en-US" nor the two letter "de" or "en") . So it is not the system language two letter iso code that helps me out, but it is a two letter representation of the browser accept language which is not provided by firefox.

So I changed the code of the DefaultNegotiation like followed an put in my AlternativeNegotiation.php in a new extension:

Made a new class AlternateNegotiation.php

[...]
foreach ($userLanguages->toArray() as $userLanguage) {

            // need a two letter user language
            $twoLetterUserLanguage = '';
            if (strlen((string)$userLanguage) > 2) {
                $twoLetterUserLanguage = substr((string)$userLanguage,0,2);
            }

            foreach ($event->getSite()->getLanguages() as $siteLanguage) {
                foreach ($compareWith as $function) {
                    $config = $siteLanguage->toArray();
                    if ($siteLanguage->enabled()
                        && ($config['excludeFromLanguageDetection'] ?? false) !== true
                        && (
                            // match the origUser language and the twoLetterUserLanguage vs the siteLanguage
                            (string)$userLanguage === $this->normalizer->normalize((string)$siteLanguage->{$function}())
                            || $twoLetterUserLanguage === $this->normalizer->normalize((string)$siteLanguage->{$function}())
                        )
                    ) {
                        $event->setSelectedLanguage($siteLanguage);

                        return;
                    }
                }
            }
        }

Services.yaml

services:
  _defaults:
    autowire: true
    autoconfigure: true
    public: false

  ME\MyLanguagedetection\:
    resource: '../Classes/*'

  ME\MyLanguagedetection\Negotiation\AlternateNegotiation:
    tags:
      - name: event.listener
        identifier: 'languageDetectionAlternateNegotiation'
        before: 'languageDetectionDefaultNegotiation'
        event: Lochmueller\LanguageDetection\Event\NegotiateSiteLanguageEvent

Thats the solution for me. Du you have any hints for me or do you think this is a feature for your extension?