diff --git a/interface/src/components/layout/LayoutAuthMenu.tsx b/interface/src/components/layout/LayoutAuthMenu.tsx index f32df06c0..1422233da 100644 --- a/interface/src/components/layout/LayoutAuthMenu.tsx +++ b/interface/src/components/layout/LayoutAuthMenu.tsx @@ -28,6 +28,7 @@ import { ReactComponent as DEflag } from '../../i18n/DE.svg'; import { ReactComponent as GBflag } from '../../i18n/GB.svg'; import { ReactComponent as SEflag } from '../../i18n/SE.svg'; import { ReactComponent as PLflag } from '../../i18n/PL.svg'; +import { ReactComponent as NOflag } from '../../i18n/NO.svg'; const ItemTypography = styled(Typography)({ maxWidth: '250px', @@ -88,10 +89,14 @@ const LayoutAuthMenu: FC = () => {  SE - +  PL + + +  NO + \ No newline at end of file diff --git a/interface/src/i18n/i18n-types.ts b/interface/src/i18n/i18n-types.ts index dfde84ba2..8cc257dfb 100644 --- a/interface/src/i18n/i18n-types.ts +++ b/interface/src/i18n/i18n-types.ts @@ -9,6 +9,7 @@ export type Locales = | 'de' | 'en' | 'nl' + | 'no' | 'pl' | 'se' diff --git a/interface/src/i18n/i18n-util.async.ts b/interface/src/i18n/i18n-util.async.ts index 9f9da27b6..fb35c3bd3 100644 --- a/interface/src/i18n/i18n-util.async.ts +++ b/interface/src/i18n/i18n-util.async.ts @@ -9,6 +9,7 @@ const localeTranslationLoaders = { de: () => import('./de'), en: () => import('./en'), nl: () => import('./nl'), + no: () => import('./no'), pl: () => import('./pl'), se: () => import('./se'), } diff --git a/interface/src/i18n/i18n-util.sync.ts b/interface/src/i18n/i18n-util.sync.ts index a87bed14b..aa81b950b 100644 --- a/interface/src/i18n/i18n-util.sync.ts +++ b/interface/src/i18n/i18n-util.sync.ts @@ -8,6 +8,7 @@ import { loadedFormatters, loadedLocales, locales } from './i18n-util' import de from './de' import en from './en' import nl from './nl' +import no from './no' import pl from './pl' import se from './se' @@ -15,6 +16,7 @@ const localeTranslations = { de, en, nl, + no, pl, se, } diff --git a/interface/src/i18n/i18n-util.ts b/interface/src/i18n/i18n-util.ts index f893ef2e6..63da3e066 100644 --- a/interface/src/i18n/i18n-util.ts +++ b/interface/src/i18n/i18n-util.ts @@ -12,10 +12,13 @@ export const locales: Locales[] = [ 'de', 'en', 'nl', + 'no', 'pl', 'se' ] +export const isLocale = (locale: string) => locales.includes(locale as Locales) + export const loadedLocales = {} as Record export const loadedFormatters = {} as Record diff --git a/interface/src/i18n/no/index.ts b/interface/src/i18n/no/index.ts new file mode 100644 index 000000000..c70c47e0e --- /dev/null +++ b/interface/src/i18n/no/index.ts @@ -0,0 +1,265 @@ +import type { BaseTranslation } from '../i18n-types'; + +const en: BaseTranslation = { + LANGUAGE: 'Language', + RETRY: 'Retry', + LOADING: 'Loading', + IS_REQUIRED: 'is required', + SIGN_IN: 'Sign In', + SIGN_OUT: 'Sign Out', + USERNAME: 'Username', + PASSWORD: 'Password', + DASHBOARD: 'Dashboard', + SETTINGS: 'Settings', + SAVED: 'saved', + HELP: 'Help', + LOGGED_IN: 'Logged in as {name}', + PLEASE_SIGNIN: 'Please sign in to continue', + UPLOAD_SUCCESSFUL: 'Upload successful', + DOWNLOAD_SUCCESSFUL: 'Download successful', + INVALID_LOGIN: 'Invalid login details', + NETWORK: 'Network', + SECURITY: 'Security', + ONOFF_CAP: 'ON/OFF', + ONOFF: 'on/off', + TYPE: 'Type', + DESCRIPTION: 'Description', + ENTITIES: 'Entities', + REFRESH: 'Refresh', + EXPORT: 'Export', + DEVICE_DETAILS: 'Device Details', + BRAND: 'Brand', + ENTITY_NAME: 'Entity Name', + VALUE: 'Value', + SHOW_FAV: 'only show favorites', + DEVICE_SENSOR_DATA: 'Device and Sensor Data', + DEVICES_SENSORS: 'Devices & Sensors', + ATTACHED_SENSORS: 'Attached EMS-ESP Sensors', + RUN_COMMAND: 'Call Command', + CHANGE_VALUE: 'Change Value', + CANCEL: 'Cancel', + RESET: 'Reset', + SEND: 'Send', + SAVE: 'Save', + REMOVE: 'Remove', + PROBLEM_UPDATING: 'Problem updating', + PROBLEM_LOADING: 'Problem loading', + ACCESS_DENIED: 'Access Denied', + ANALOG_SENSOR: 'Analog Sensor', + ANALOG_SENSORS: 'Analog Sensors', + UPDATED: 'Updated', + UPDATE: 'Update', + REMOVED: 'Removed', + DELETION: 'Deletion', + OFFSET: 'Offset', + FACTOR: 'Factor', + FREQ: 'Frequency', + STARTVALUE: 'Start value', + WARN_GPIO: 'Warning: be careful when assigning a GPIO!', + EDIT: 'Edit', + TEMP_SENSOR: 'Temperature Sensor', + TEMP_SENSORS: 'Temperature Sensors', + WRITE_COMMAND: 'Write command {cmd}', + EMS_BUS_WARNING: + 'EMS bus disconnected. If this warning still persists after a few seconds please check settings and board profile', + EMS_BUS_SCANNING: 'Scanning for EMS devices...', + CONNECTED: 'Connected', + TX_ISSUES: 'Tx issues - try a different Tx Mode', + DISCONNECTED: 'Disconnected', + EMS_SCAN: 'Are you sure you want to initiate a full device scan of the EMS bus?', + EMS_BUS_STATUS: 'EMS Bus Status', + ACTIVE_DEVICES: 'Active Devices & Sensors', + DEVICE: 'Device', + SUCCESS: 'SUCCESS', + FAIL: 'FAIL', + QUALITY: 'QUALITY', + SCAN_DEVICES: 'Scan for new devices', + EMS_BUS_STATUS_TITLE: 'EMS Bus & Activity Status', + SCAN: 'Scan', + STATUS_NAMES: [ + 'EMS Telegrams Received (Rx)', + 'EMS Reads (Tx)', + 'EMS Writes (Tx)', + 'Temperature Sensor Reads', + 'Analog Sensor Reads', + 'MQTT Publishes', + 'API Calls', + 'Syslog Messages' + ], + NUM_DEVICES: '{num} Device{{s}}', + NUM_TEMP_SENSORS: '{num} Temperature Sensor{{s}}', + NUM_ANALOG_SENSORS: '{num} Analog Sensor{{s}}', + NUM_DAYS: '{num} Day{{s}}', + NUM_SECONDS: '{num} Second{{s}}', + NUM_HOURS: '{num} Hour{{s}}', + NUM_MINUTES: '{num} Minute{{s}}', + APPLICATION_SETTINGS: 'Application Settings', + CUSTOMIZATION: 'Customization', + APPLICATION_RESTARTING: 'EMS-ESP is restarting', + BOARD_PROFILE_TEXT: + 'Select a pre-configured interface board profile from the list below or choose Custom to configure your own hardware settings', + BOARD_PROFILE: 'Board Profile', + BUTTON: 'Button', + TEMPERATURE: 'Temperature', + DISABLED: 'disabled', + GENERAL_OPTIONS: 'General Options', + LANGUAGE_ENTITIES: 'Language (for device entities)', + HIDE_LED: 'Hide LED', + ENABLE_TELNET: 'Enable Telnet Console', + ENABLE_ANALOG: 'Enable Analog Sensors', + CONVERT_FAHRENHEIT: 'Convert temperature values to Fahrenheit', + BYPASS_TOKEN: 'Bypass Access Token authorization on API calls', + READONLY: 'Enable read-only mode (blocks all outgoing EMS Tx Write commands)', + UNDERCLOCK_CPU: 'Underclock CPU speed', + ENABLE_SHOWER_TIMER: 'Enable Shower Timer', + ENABLE_SHOWER_ALERT: 'Enable Shower Alert', + TRIGGER_TIME: 'Trigger Time', + COLD_SHOT_DURATION: 'Cold Shot Duration', + FORMATTING_OPTIONS: 'Formatting Options', + BOOLEAN_FORMAT_DASHBOARD: 'Boolean Format Dashboard', + BOOLEAN_FORMAT_API: 'Boolean Format API/MQTT', + ENUM_FORMAT: 'Enum Format API/MQTT', + INDEX: 'Index', + ENABLE_PARASITE: 'Enable parasite power', + LOGGING: 'Logging', + LOG_HEX: 'Log EMS telegrams in hexadecimal', + ENABLE_SYSLOG: 'Enable Syslog', + MARK_INTERVAL: 'Mark Interval', + SECONDS: 'seconds', + MINUTES: 'minutes', + RESTART: 'Restart', + HOURS: 'hours', + RESTART_TEXT: 'EMS-ESP needs to be restarted to apply changed system settings', + COMMAND: 'Command', + CUSTOMIZATIONS_RESTART: 'All customizations have been removed. Restarting...', + CUSTOMIZATIONS_FULL: 'Selected entities exceeded limit. Please save in batches', + CUSTOMIZATIONS_SAVED: 'Customizations saved', + CUSTOMIZATIONS_HELP_1: 'Select a device and customize the entities options or click to rename', + CUSTOMIZATIONS_HELP_2: 'mark as favorite', + CUSTOMIZATIONS_HELP_3: 'disable write action', + CUSTOMIZATIONS_HELP_4: 'exclude from MQTT and API', + CUSTOMIZATIONS_HELP_5: 'hide from Dashboard', + SELECT_DEVICE: 'Select a device', + SET_ALL: 'set all', + OPTIONS: 'Options', + NAME: 'Name', + CUSTOMIZATIONS_RESET: + 'Are you sure you want remove all customizations including the custom settings of the Temperature and Analog sensors?', + DEVICE_ENTITIES: 'Device Entities', + USER_CUSTOMIZATION: 'User Customization', + SUPPORT_INFORMATION: 'Support Information', + CLICK_HERE: 'Click Here', + HELP_INFORMATION_1: 'Visit the online wiki to get instructions on how to configure EMS-ESP', + HELP_INFORMATION_2: 'For live community chat join our Discord server', + HELP_INFORMATION_3: 'To request a feature or report a bug', + HELP_INFORMATION_4: 'remember to download and attach your system information for a faster response when reporting an issue', + HELP_INFORMATION_5: + "EMS-ESP is a free and open-source project. Please support its future development by giving it a star on Github!", + SUPPORT_INFO: 'Support Info', + UPLOAD: 'Upload', + DOWNLOAD: 'Download', + ABORTED: 'aborted', + FAILED: 'failed', + SUCCESSFUL: 'successful', + SYSTEM: 'System', + LOG: 'Log', + STATUS: 'Status', + UPLOAD_DOWNLOAD: 'Upload/Download', + SYSTEM_VERSION_RUNNING: 'You are currently running version', + SYSTEM_APPLY_FIRMWARE: 'to apply the new firmware', + CLOSE: 'Close', + USE: 'Use', + FACTORY_RESET: 'Factory Reset', + SYSTEM_FACTORY_TEXT: 'Device has been factory reset and will now restart', + SYSTEM_FACTORY_TEXT_DIALOG: 'Are you sure you want to reset the device to its factory defaults?', + VERSION_CHECK: 'Version Check', + THE_LATEST: 'The latest', + PLATFORM: 'Device (Platform / SDK)', + UPTIME: 'System Uptime', + CPU_FREQ: 'CPU Frequency', + HEAP: 'Heap (Free / Max Alloc)', + PSRAM: 'PSRAM (Size / Free)', + FLASH: 'Flash Chip (Size / Speed)', + FILESYSTEM: 'File System (Used / Total)', + BUFFER_SIZE: 'Buffer Size', + COMPACT: 'Compact', + ENABLE_OTA: 'Enable OTA Updates', + DOWNLOAD_CUSTOMIZATION_TEXT: 'Download the entity customizations', + DOWNLOAD_SETTINGS_TEXT: + 'Download the application settings. Be careful when sharing your settings as this file contains passwords and other sensitive system information', + UPLOAD_TEXT: 'Upload a new firmware (.bin) file, settings or customizations (.json) file below', + UPLOADING: 'Uploading', + UPLOAD_DROP_TEXT: 'Drop file or click here', + ERROR: 'Unexpected Error, please try again', + TIME_SET: 'Time set', + MANAGE_USERS: 'Manage Users', + IS_ADMIN: 'is Admin', + USER_WARNING: 'You must have at least one admin user configured', + ADD: 'Add', + ACCESS_TOKEN_FOR: 'Access Token for', + ACCESS_TOKEN_TEXT: + 'The token below is used with REST API calls that require authorization. It can be passed either as a Bearer token in the Authorization header or in the access_token URL query parameter.', + GENERATING_TOKEN: 'Generating token', + USER: 'User', + MODIFY: 'Modify', + SU_TEXT: + 'The su (super user) password is used to sign authentication tokens and also enable admin privileges within the Console.', + NOT_ENABLED: 'Not enabled', + ERRORS: 'Errors', + DISCONNECT_REASON: 'Disconnect Reason', + ENABLE_MQTT: 'Enable MQTT', + OPTIONAL: 'Optional', + FORMATTING: 'Formatting', + FORMAT: 'Format', + MQTT_NEST_1: 'Nested in a single topic', + MQTT_NEST_2: 'As individual topics', + MQTT_RESPONSE: 'Publish command output to a `response` topic', + MQTT_PUBLISH_TEXT_1: 'Publish single value topics on change', + MQTT_PUBLISH_TEXT_2: 'Publish to command topics (ioBroker)', + MQTT_PUBLISH_TEXT_3: 'Enable MQTT Discovery (Home Assistant, Domoticz)', + MQTT_PUBLISH_TEXT_4: 'Prefix for the Discovery topics', + MQTT_PUBLISH_INTERVALS: 'Publish Intervals', + MQTT_INT_BOILER: 'Boilers and Heat Pumps', + MQTT_INT_THERMOSTATS: 'Thermostats', + MQTT_INT_SOLAR: 'Solar Modules', + MQTT_INT_MIXER: 'Mixer Modules', + DEFAULT: 'Default', + MQTT_CLEAN_SESSION: 'Set Clean Session', + MQTT_RETAIN_FLAG: 'Always set Retain flag', + INACTIVE: 'Inactive', + ACTIVE: 'Active', + UNKNOWN: 'Unknown', + SET_TIME: 'Set Time', + SET_TIME_TEXT: 'Enter local date and time below to set the time', + LOCAL_TIME: 'Local Time', + UTC_TIME: 'UTC Time', + ENABLE_NTP: 'Enable NTP', + TIME_ZONE: 'Time Zone', + ACCESS_POINT: 'Access Point', + AP_PROVIDE: 'Enable Access Point', + AP_PROVIDE_TEXT_1: 'always', + AP_PROVIDE_TEXT_2: 'when WiFi is disconnected', + AP_PROVIDE_TEXT_3: 'never', + AP_PREFERRED_CHANNEL: 'Preferred Channel', + AP_HIDE_SSID: 'Hide SSID', + NETWORK_SCAN: 'Scan WiFi Networks', + IDLE: 'Idle', + LOST: 'Lost', + SCANNING: 'Scanning', + SCAN_AGAIN: 'Scan again', + NETWORK_SCANNER: 'Network Scanner', + NETWORK_NO_WIFI: 'No WiFi networks found', + NETWORK_BLANK_SSID: 'leave blank to disable WiFi', + POWER: 'Power', + NETWORK_DISABLE_SLEEP: 'Disable WiFi Sleep Mode', + NETWORK_LOW_BAND: 'Use Lower WiFi Bandwidth', + NETWORK_USE_DNS: 'Enable mDNS Service', + NETWORK_ENABLE_IPV6: 'Enable IPv6 support', + NETWORK_FIXED_IP: 'Use Fixed IP address', + ADMIN: 'Admin', + GUEST: 'Guest', + NEW: 'New', + RENAME: 'Rename' +}; + +export default en; diff --git a/interface/src/project/SettingsApplication.tsx b/interface/src/project/SettingsApplication.tsx index f27fa1b2f..c4df56b45 100644 --- a/interface/src/project/SettingsApplication.tsx +++ b/interface/src/project/SettingsApplication.tsx @@ -342,7 +342,8 @@ const SettingsApplication: FC = () => { Deutsch (DE) Nederlands (NL) Svenska (SE) - Polski (PL) + Polski (PL) + Norsk (NO) {data.led_gpio !== 0 && ( diff --git a/src/locale_translations.h b/src/locale_translations.h index 6252bfb0b..91e2a48cc 100644 --- a/src/locale_translations.h +++ b/src/locale_translations.h @@ -24,6 +24,7 @@ #define EMSESP_LOCALE_NL "nl" #define EMSESP_LOCALE_SE "se" #define EMSESP_LOCALE_PL "pl" +#define EMSESP_LOCALE_NO "no" // translations are in order en, de,nl, se.... // if there is no translation, it will default to en diff --git a/src/system.cpp b/src/system.cpp index 1dc87f4b6..4a3d0217a 100644 --- a/src/system.cpp +++ b/src/system.cpp @@ -42,7 +42,7 @@ namespace emsesp { // Languages supported. Note: the order is important and must match locale_translations.h -const char * const languages[] = {EMSESP_LOCALE_EN, EMSESP_LOCALE_DE, EMSESP_LOCALE_NL, EMSESP_LOCALE_SE, EMSESP_LOCALE_PL}; +const char * const languages[] = {EMSESP_LOCALE_EN, EMSESP_LOCALE_DE, EMSESP_LOCALE_NL, EMSESP_LOCALE_SE, EMSESP_LOCALE_PL, EMSESP_LOCALE_NO}; size_t num_languages = sizeof(languages) / sizeof(const char *);