80

Something similar to [NSLocale currentLocale] in Objective-C.

faaez
  • 881
  • 1
  • 7
  • 6

15 Answers15

98

There's no need for an external library. You can find what you're looking for in React's Native Modules

import { NativeModules } from 'react-native'

// iOS:
const locale = NativeModules.SettingsManager.settings.AppleLocale ||
               NativeModules.SettingsManager.settings.AppleLanguages[0] // "fr_FR"

// Android:
const locale = NativeModules.I18nManager.localeIdentifier // "fr_FR"

To test this, I changed the language on my device to French. Here's a sample of what you'll find in the NativeModules.SettingsManager.settings object related to locale:

{
    ...
    AppleKeyboards: [
        "fr_FR@hw=US;sw=QWERTY",
        "en_US@sw=QWERTY;hw=Automatic",
        "es_419@sw=QWERTY-Spanish;hw=Automatic",
        "emoji@sw=Emoji"
    ]
    AppleLanguages: ["fr-US", "en-US", "es-US", "en"]
    AppleLanguagesDidMigrate: "9.2"
    AppleLocale: "fr_FR"
    NSLanguages: ["fr-US", "en-US", "es-US", "en"]
    ...
}
evan_schmevan
  • 1,591
  • 12
  • 19
  • 1
    @DanielSteigerwald Accessing settings in this way is not yet supported on Android. See [Settings.android.js](https://github.com/facebook/react-native/blob/94666f16c7da37e649316d40ea23d7a8054a04f9/Libraries/Settings/Settings.android.js) – evan_schmevan Sep 12 '16 at 17:22
  • 11
    Use `NativeModules.I18nManager.localeIdentifier` for Android – Matt Stow Dec 14 '16 at 03:05
  • @evan_schmevan In ios NativeModules.SettingsManager is undefined and NativeModules is an empty object... :( ! Do you know what can be the reason? – Aral Roca Dec 15 '18 at 14:05
  • 1
    @AralRoca are you using Expo by chance? It looks like it's an empty object when testing on Expo, but everything works as expected on an iOS simulator and real device. – evan_schmevan Dec 21 '18 at 16:40
  • I use this technique with Expo 33.0.0 and it works great, even when testing on Expo. – Fl4v Jul 26 '19 at 20:49
  • 5
    This appears to break on iOS13, when the native app built with the iOS13 SDK. – TomSwift Sep 20 '19 at 18:59
  • 3
    @TomSwift It seems like this is only the case on the simulator. It works fine on my iOS 13 device. – Evrim Persembe Sep 24 '19 at 13:26
  • If `NativeModules.SettingsManager` is `null`, you also need to link the `react-native/RCTSettings` library by either adding `RCTSettings` to your Podfile and re-running `pod install`, or manually by following the guide here: https://reactnative.dev/docs/linking-libraries-ios.html – James May 17 '20 at 15:09
  • As of ios 14, both `AppleLocale` and `AppleLanguages` seem to be defined. Would recommend picking `AppleLanguages` first now, since that supports the app specific prefered languages feature. and use optional chaining to better allow for backward compatibility – Karthik T May 05 '21 at 08:10
76
import { Platform, NativeModules } from 'react-native'

const deviceLanguage =
      Platform.OS === 'ios'
        ? NativeModules.SettingsManager.settings.AppleLocale ||
          NativeModules.SettingsManager.settings.AppleLanguages[0] //iOS 13
        : NativeModules.I18nManager.localeIdentifier;

console.log(deviceLanguage); //en_US
Firoz Ahmed
  • 1,929
  • 16
  • 18
  • 4
    As of iOS 13 AppleLocale no longer appears to be defined. Anyone have a workaround for iOS 13? – user3866793 Sep 23 '19 at 05:50
  • @user3866793 `NativeModules.SettingsManager.settings.AppleLanguages` contains an array of languages, see https://stackoverflow.com/a/58063292 – carlbolduc Oct 22 '19 at 15:26
  • 2
    As of ios 14, both `AppleLocale` and `AppleLanguages` seem to be defined. Would recommend picking `AppleLanguages` first now, since that supports the app specific prefered languages feature. and use optional chaining to better allow for backward compatibility – Karthik T May 05 '21 at 08:10
14

I am using the i18n package (react-native-i18n). And then it's just:

I18n = require('react-native-i18n')
locale = I18n.currentLocale()
eyal83
  • 3,893
  • 3
  • 19
  • 30
8

Nothing of the above worked for me, but this component.

console.log("Device Locale", DeviceInfo.getDeviceLocale()); // e.g en-US
br4nnigan
  • 646
  • 6
  • 13
  • Very nice package, but currently not maintained anymore - the author is looking for someone to take over (at the time I'm posting this). Fingers crossed somebody will pick it up. – Philipp Sumi Jan 13 '19 at 15:50
  • the react community picked it https://github.com/react-native-community/react-native-device-info – Sayuri Mizuguchi Jul 08 '20 at 16:34
  • 4
    And removed getDeviceLocale() (https://github.com/react-native-device-info/react-native-device-info/blob/master/CHANGELOG.md#300-beta1) to "remove API duplication in the react-native-community modules"; use https://github.com/zoontek/react-native-localize – swooby Oct 21 '20 at 22:29
5
function getLocale() {
  if (React.Platform.OS === 'android') {
    return I18n.locale;
  } else {
    return NativeModules.SettingsManager.settings.AppleLocale.replace(/_/, '-');
  }
}
RogerParis
  • 1,549
  • 1
  • 13
  • 24
2

iOS 13 workaround here:

locale = NativeModules.SettingsManager.settings.AppleLocale // "fr_FR"
console.log(" ==> Current settings: ", NativeModules.SettingsManager.settings)
if (locale === undefined) {
    // iOS 13 workaround, take first of AppleLanguages array 
    locale = NativeModules.SettingsManager.settings.AppleLanguages[0]
    if (locale == undefined) {
          return "en" // default language
    }
}
1

You can install react-native-i18n and use this function:

import React, { NativeModules } from 'react-native'
...
function getLocale () {
  if (React.Platform.OS === 'android') {
    return NativeModules.RNI18n.getCurrentLocale(locale => locale.replace(/_/, '-'))
  } else {
    return NativeModules.RNI18n.locale.replace(/_/, '-')
  }
}

Works both under Android and iOS.

amb
  • 4,798
  • 6
  • 41
  • 68
1

This code is future proof

import {NativeModules} from 'react-native';

function getSystemLocale(): string {
  let locale: string;
  // iOS
  if (
    NativeModules.SettingsManager &&
    NativeModules.SettingsManager.settings &&
    NativeModules.SettingsManager.settings.AppleLanguages
  ) {
    locale = NativeModules.SettingsManager.settings.AppleLanguages[0];
    // Android
  } else if (NativeModules.I18nManager) {
    locale = NativeModules.I18nManager.localeIdentifier;
  }

  if (typeof locale === 'undefined') {
    console.log('Couldnt get locale');
    return 'en';
  }

  return locale;
}

export default {
  getSystemLocale,
};
Codler
  • 10,951
  • 6
  • 52
  • 65
1
$ npm install --save react-native-localize

--- or ---

$ yarn add react-native-localize

import * as RNLocalize from "react-native-localize";

console.log(RNLocalize.getLocales());

let defaultLanguage = RNLocalize.getLocales()[0].languageCode;

console.log('defaultLanguage', defaultLanguage);
Kamil Sarna
  • 5,993
  • 1
  • 32
  • 22
0

You may need to extend react native yourself to get this info. But, depending on your use case, this localization component (stefalda/ReactNativeLocalization) may work for you.

Chris Geirman
  • 9,474
  • 5
  • 37
  • 70
0

I found this solution for Android and iOS (RN 0.35)

import React, {NativeModules} from 'react-native';

if (NativeModules.I18nManager) {
    const {localeIdentifier, isRTL} = NativeModules.I18nManager;
}

May be this will help to someone, but iOS not shows locale property. It shows only rtl support now.

SerzN1
  • 1,814
  • 23
  • 15
0

if you develop over Expo... you can use:

console.log(await NativeModules.ExponentUtil.getCurrentLocaleAsync());
console.log(await NativeModules.ExponentUtil.getCurrentDeviceCountryAsync());
console.log(await NativeModules.ExponentUtil.getCurrentTimeZoneAsync());

crazyx13th
  • 533
  • 5
  • 10
0

NativeModules solution can be changed over time by Facebook developers.
Because of this reason I had prepared a component. (It works only on Android for now)

Sample usage:

import SystemSettings from 'react-native-system-settings'

SystemSettings.get(
    settings => console.log('settings: ', settings)
)

Also promise-then can be used:

SystemSettings.get().then(settings => console.log('settings: ', settings)).done()

Also ES7 async-await method can be used!

class App extends React.Component {
    componentWillMount() {
        this._loadInitialState()
    }

    _loadInitialState = async () => {
        try {
            let settings = await SystemSettings.get()
            // Now settings variable would be filled and can be used!
        } catch (error) {}
    };
}

A sample result:

{
    densityDpi: 320,
    fontScale: 1,
    hardKeyboardHidden: "no",
    keyboard: "qwerty",
    keyboardHidden: "no",
    localization: {
        country: "US",
        displayCountry: "United States",
        displayLanguage: "English",
        displayName: "English (United States)",
        is24HourFormat: false,
        language: "en",
        locale: "en_US",
        networkCountry: "US",
        simCountry: "US",
        timeZone: {
            ID: "Europe/Amsterdam",
            displayName: {
                long: "Amsterdam Standard Time",
                short: "GMT+01:00",
            },
            offset: 3600000
        }
    },
    orientation: "portrait",
    screenHeightDp: 615,
    screenLayout: "normal",
    screenWidthDp: 360,
    smallestScreenWidthDp: 360,
    uiModeType: "normal"
}
efkan
  • 12,991
  • 6
  • 73
  • 106
0

Personally I prefer use react-native-i18n. then you can use like this inside the documentation..

import { getLanguages } from 'react-native-i18n'

getLanguages().then(languages => {
  console.log(languages) // ['en-US', 'en']
})

link: https://github.com/AlexanderZaytsev/react-native-i18n

Hazim Ali
  • 1,077
  • 4
  • 17
  • 28
-1

I am using react-native-i18n

in order to access the device's language I used:

import { getLanguages } from 'react-native-i18n';

getLanguages().then(languages => {
  console.log(languages); // ['en-US', 'en']
});

It's all in the documentation.

Luminita Balas
  • 604
  • 1
  • 5
  • 4