Подтвердить что ты не робот

Использование языковых настроек для определения того, как использовать имперские единицы

Я работаю над приложением, которое хочет отображать длины либо в сантиметрах (см), либо в дюймах ("). Есть ли способ выбрать правильное устройство из локали? В любом случае я тоже собираюсь поставьте опцию, чтобы пользователь мог переопределить настройку локали.

США, Либерия и Бирма должны использовать имперские юниты и остальную часть мира. Один из способов - включить эту логику в свои классы, но я бы предпочел использовать любую встроенную логику, если она доступна. Любые указатели?

4b9b3361

Ответ 1

В конце концов я выбрал следующее решение.

public class UnitLocale {
    public static UnitLocale Imperial = new UnitLocale();
    public static UnitLocale Metric = new UnitLocale();

    public static UnitLocale getDefault() {
            return getFrom(Locale.getDefault());
    }
    public static UnitLocale getFrom(Locale locale) {
        String countryCode = locale.getCountry();
        if ("US".equals(countryCode)) return Imperial; // USA
        if ("LR".equals(countryCode)) return Imperial; // Liberia
        if ("MM".equals(countryCode)) return Imperial; // Myanmar
        return Metric;
    }
}

Например, используйте это так.

if (UnitLocale.getDefault() == UnitLocale.Imperial) convertToimperial();

Если также необходимы методы преобразования, их предпочтительно можно добавить в подклассы UnitLocale. Мне нужно было только обнаружить, использовать ли имперские юниты и отправить их на сервер.

Использование int поверх java-объектов приводит к чрезвычайно низкому приросту производительности и усложняет чтение кода. Сравнение двух ссылок в Java сопоставимо по скорости со сравнением двух ints. Кроме того, используя объекты позволяют добавлять методы к UnitLocale класса или подкласса, таких как, convertToMetric и т.д.

Вы также можете использовать перечисление, если вы предпочитаете это.

Ответ 2

  • Программным

Небольшое улучшение в решении от @vidstige

Я бы использовал getCountry(). toUpperCase(), чтобы быть безопасным и изменить проверки на коммутатор для более чистого кода. Что-то вроде этого:

public static UnitLocale getFrom(Locale locale) {
    String countryCode = locale.getCountry().toUpperCase();
    switch (countryCode) {
        case "US":
        case "LR":
        case "MM":
            return Imperial;
        default:
            return Metric;
    }
}
  1. Из ресурсов

Другим решением может быть создание папок ресурсов для каждой страны, например: [values_US] [values_LR] [values_MM] с логическим ресурсом, измененным на true. Затем прочитайте этот логический ресурс из кода.

Ответ 3

Просто дайте пользователю возможность выбрать предпочтительный блок в меню настроек. Если это путешествующий пользователь, вы не хотите, чтобы приложение было географически известно, IMO.

Ответ 4

Основываясь на других хороших решениях здесь, вы также можете реализовать это как функцию расширения Kotlin для объекта Locale:

fun Locale.isMetric(): Boolean {
    return when (country.toUpperCase()) {
        "US", "LR", "MM" -> false
        else -> true
    }
}

Таким образом, все, что вам нужно сделать, это позвонить:

val metric = Locale.getDefault().isMetric()

Ответ 5

Более или менее полный способ сделать это заключается в следующем.

Котлин:

private fun Locale.toUnitSystem() =
    when (country.toUpperCase()) {
        // https://en.wikipedia.org/wiki/United_States_customary_units
        // https://en.wikipedia.org/wiki/Imperial_units
        "US" -> UnitSystem.IMPERIAL_US
        // UK, Myanmar, Liberia, 
        "GB", "MM", "LR" -> UnitSystem.IMPERIAL
        else -> UnitSystem.METRIC
    }

Обратите внимание, что существует разница между британскими и американскими имперскими системами, подробности см. В вики-статьях.