Ответ 1
Если вы предоставляете языковые альтернативы с одинаковым приоритетом, порядок списка становится значительным. Это становится очевидным при проверке разобранного списка "en-US;q=1.0,en-GB;q=1.0"
. Он содержит две записи, представляющие "en-US;q=1.0"
, а затем "en-GB;q=1.0"
См. https://www.ietf.org/rfc/rfc4647.txt
3.4. Поиск
Поиск используется для выбора единственного языкового тега, который наилучшим образом соответствует список приоритетов языка для данного запроса. При выполнении поиск, каждый языковой диапазон в списке приоритетов языка в свою очередь, в соответствии с приоритетом.... Первый совпадающий тег найден, согласно приоритет пользователя считается самым близким совпадением и является элементом вернулся. Например, если языковой диапазон "de-ch", поиск операция может создавать контент с тегами "de" или "de-CH", но никогда содержимое с тегом "de-CH-1996". Если языковой тег не соответствует запрос, возвращается значение "по умолчанию".
...
В схеме поиска языковой диапазон постепенно усекается от конца до тех пор, пока не будет найден соответствующий языковой тег....
Последнее предложение описывает то, что уже сказано в примере в первом абзаце, то есть диапазон языков de-CH
может соответствовать либо de-CH
, либо de
. Этот поиск с отступлением выполняется для каждого элемента списка, останавливаясь на первом, для которого найдено совпадение.
Другими словами, указание "en-US;q=1.0,en-GB;q=1.0"
похоже на указание "en-US,en,en-GB,en"
.
Возможно, что вы хотите фильтровать, см.
3.3. Фильтрация
Фильтрация используется для выбора набора языковых тегов, который соответствует данный список приоритетов языка....
При фильтрации каждый диапазон языков представляет собой наименее конкретный языковой тег (т.е. тег языка с наименьшим числом subtags), что является приемлемым совпадением.
Таким образом, учитывая ваш исходный список выбираемых локалей
List<Locale> filtered = Locale.filter(
Locale.LanguageRange.parse("en-US;q=1.0,en-GB;q=1.0"), locales);
System.out.println("filtered: "+filtered);
создает [en_GB]
.
тогда
Collection<Locale> locales = Arrays.asList(Locale.forLanguageTag("en"),
Locale.forLanguageTag("en-GB"), Locale.forLanguageTag("en-US"));
List<Locale> filtered = Locale.filter(
Locale.LanguageRange.parse("en-US;q=1.0,en-GB;q=1.0"), locales);
System.out.println("filtered: "+filtered);
производит [en_US, en_GB]
(обратите внимание на приоритетный порядок и отсутствие резервной копии en
). Поэтому в зависимости от контекста вы можете сначала попытаться выбрать из отфильтрованного списка и прибегать к поиску, когда отфильтрованный список пуст.
По крайней мере, поведение реализации Javas соответствует спецификации. Как вы уже отметили, изменение приоритета или изменение порядка (когда приоритет равен), изменяет результат в соответствии со спецификацией.