diff --git a/.github/workflows/i18n-crowdin-download.yml b/.github/workflows/i18n-crowdin-download.yml index 13a8873fef6..526876bbd81 100644 --- a/.github/workflows/i18n-crowdin-download.yml +++ b/.github/workflows/i18n-crowdin-download.yml @@ -152,12 +152,12 @@ jobs: run: | filesChanged="$(gh pr diff --name-only ${{ steps.crowdin-download.outputs.pull_request_url }})" - if [[ $(echo "$filesChanged" | grep -cv -e 'public/locales/[a-zA-Z\-]*/grafana.json' -e 'public/app/plugins/datasource/azuremonitor/locales/[a-zA-Z\-]*/grafana-azure-monitor-datasource.json') -ne 0 ]]; then + if [[ $(echo "$filesChanged" | grep -cv -e 'public/locales/[a-zA-Z\-]*/grafana.json' -e 'public/app/plugins/datasource/azuremonitor/locales/[a-zA-Z\-]*/grafana-azure-monitor-datasource.json' -e 'public/app/plugins/datasource/mssql/locales/[a-zA-Z\-]*/mssql.json') -ne 0 ]]; then echo "Non-i18n changes detected, not approving" exit 1 fi - if [[ $(echo "$filesChanged" | grep -c -e "public/locales/en-US" -e "public/app/plugins/datasource/azuremonitor/locales/en-US") -ne 0 ]]; then + if [[ $(echo "$filesChanged" | grep -c -e "public/locales/en-US" -e "public/app/plugins/datasource/azuremonitor/locales/en-US" -e "public/app/plugins/datasource/mssql/locales/en-US") -ne 0 ]]; then echo "en-US changes detected, not approving" exit 1 fi diff --git a/.github/workflows/i18n-crowdin-upload.yml b/.github/workflows/i18n-crowdin-upload.yml index 998829921cd..60f33de876f 100644 --- a/.github/workflows/i18n-crowdin-upload.yml +++ b/.github/workflows/i18n-crowdin-upload.yml @@ -6,6 +6,7 @@ on: paths: - 'public/locales/en-US/grafana.json' - 'public/app/plugins/datasource/azuremonitor/locales/en-US/grafana-azure-monitor-datasource.json' + - 'public/app/plugins/datasource/mssql/locales/en-US/mssql.json' branches: - main diff --git a/crowdin.yml b/crowdin.yml index e27a7887138..59366d9a3c0 100644 --- a/crowdin.yml +++ b/crowdin.yml @@ -15,4 +15,10 @@ files: [ "type": "i18next_json", "dest": "plugins/azuremonitor/en-US/%original_file_name%" }, + { + "source": "public/app/plugins/datasource/mssql/locales/en-US/mssql.json", + "translation": "public/app/plugins/datasource/mssql/locales/%locale%/%original_file_name%", + "type": "i18next_json", + "dest": "plugins/mssql/en-US/%original_file_name%" + }, ] diff --git a/eslint.config.js b/eslint.config.js index 666e275dae1..39937809dfc 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -19,7 +19,7 @@ const getEnvConfig = require('./scripts/webpack/env-util'); const envConfig = getEnvConfig(); const enableBettererRules = envConfig.frontend_dev_betterer_eslint_rules; -const pluginsToTranslate = ['public/app/plugins/datasource/azuremonitor']; +const pluginsToTranslate = ['public/app/plugins/datasource/azuremonitor', 'public/app/plugins/datasource/mssql']; /** * @type {Array} diff --git a/pkg/registry/apis/provisioning/jobs/migrate/mock_bulk_process_client.go b/pkg/registry/apis/provisioning/jobs/migrate/mock_bulk_process_client.go index 15051cd430e..e16d5695c0d 100644 --- a/pkg/registry/apis/provisioning/jobs/migrate/mock_bulk_process_client.go +++ b/pkg/registry/apis/provisioning/jobs/migrate/mock_bulk_process_client.go @@ -7,7 +7,7 @@ import ( mock "github.com/stretchr/testify/mock" metadata "google.golang.org/grpc/metadata" - + "github.com/grafana/grafana/pkg/storage/unified/resourcepb" ) diff --git a/public/app/plugins/datasource/mssql/CheatSheet.tsx b/public/app/plugins/datasource/mssql/CheatSheet.tsx index 8ca5aeeed24..da7cefa99b1 100644 --- a/public/app/plugins/datasource/mssql/CheatSheet.tsx +++ b/public/app/plugins/datasource/mssql/CheatSheet.tsx @@ -1,6 +1,7 @@ import { css } from '@emotion/css'; import { GrafanaTheme2 } from '@grafana/data'; +import { Trans } from '@grafana/i18n'; import { useStyles2 } from '@grafana/ui'; export function CheatSheet() { @@ -8,29 +9,54 @@ export function CheatSheet() { return (
-

MSSQL cheat sheet

- Time series: +

+ MSSQL cheat sheet +

+ Time series: - Optional: + Optional: -

Resultsets of time series queries need to be sorted by time.

- Table: +

+ + Resultsets of time series queries need to be sorted by time. + +

+ Table: - Macros: + Macros: + {/* eslint-disable @grafana/no-untranslated-strings */} -

Example of group by and order by with $__timeGroup:

+ {/* eslint-enable @grafana/no-untranslated-strings */} +

+ + Example of group by and order by with {'{{timeGroupMacro}}'}: + +

+ {/* eslint-disable @grafana/no-untranslated-strings */}
         
           SELECT $__timeGroup(date_time_col, '1h') AS time, sum(value) as value 
@@ -67,7 +102,11 @@ export function CheatSheet() {
- Or build your own conditionals using these macros which just return the values: + {/* eslint-enable @grafana/no-untranslated-strings */} + + Or build your own conditionals using these macros which just return the values: + + {/* eslint-disable @grafana/no-untranslated-strings */} + {/* eslint-enable @grafana/no-untranslated-strings */}
); } diff --git a/public/app/plugins/datasource/mssql/azureauth/AzureCredentialsForm.tsx b/public/app/plugins/datasource/mssql/azureauth/AzureCredentialsForm.tsx index f7681d27013..17d45809fcf 100644 --- a/public/app/plugins/datasource/mssql/azureauth/AzureCredentialsForm.tsx +++ b/public/app/plugins/datasource/mssql/azureauth/AzureCredentialsForm.tsx @@ -2,6 +2,7 @@ import { ChangeEvent } from 'react'; import { AzureCredentials, AzureAuthType } from '@grafana/azure-sdk'; import { SelectableValue } from '@grafana/data'; +import { Trans, useTranslate } from '@grafana/i18n'; import { Button, Field, Select, Input } from '@grafana/ui'; export interface Props { @@ -22,6 +23,7 @@ export const AzureCredentialsForm = (props: Props) => { onCredentialsChange, disabled, } = props; + const { t } = useTranslate(); const onAuthTypeChange = (selected: SelectableValue) => { if (onCredentialsChange) { @@ -116,27 +118,30 @@ export const AzureCredentialsForm = (props: Props) => { const authTypeOptions: Array> = [ { value: 'clientsecret', - label: 'App Registration', + label: t('azureauth.azure-credentials-form.auth-options-app-registration', 'App Registration'), }, ]; if (managedIdentityEnabled) { authTypeOptions.push({ value: 'msi', - label: 'Managed Identity', + label: t('azureauth.azure-credentials-form.auth-options-managed-identity', 'Managed Identity'), }); } if (azureEntraPasswordCredentialsEnabled) { authTypeOptions.push({ value: 'ad-password', - label: 'Azure Entra Password', + label: t('azureauth.azure-credentials-form.auth-options-azure-entra', 'Azure Entra Password'), }); } return (
opt.value === credentials.azureCloud)} options={azureCloudOptions} onChange={onAzureCloudChange} isDisabled={disabled} inputId="azure-cloud-type" - aria-label="Azure Cloud" + aria-label={t('azureauth.azure-credentials-form.aria-label-azure-cloud', 'Azure Cloud')} width={20} /> )} {!disabled && (typeof credentials.clientSecret === 'symbol' ? ( - +
) : ( { )} {credentials.authType === 'ad-password' && azureEntraPasswordCredentialsEnabled && ( <> - + {!disabled && (typeof credentials.password === 'symbol' ? ( - +
) : ( - - The database user should only be granted SELECT permissions on the specified database and tables you want to - query. Grafana does not validate that queries are safe so queries can contain any SQL statement. For example, - statements like USE otherdb; and DROP TABLE user; would be executed. To protect - against this we highly recommend you create a specific MS SQL user with restricted permissions. Check - out the{' '} - - Microsoft SQL Server Data Source Docs - {' '} - for more information. + + + The database user should only be granted {'{{permissionType}}'} permissions on the specified database and + tables you want to query. Grafana does not validate that queries are safe so queries can contain any SQL + statement. For example, statements like {'{{example1}}'} and {'{{example2}}'} would + be executed. To protect against this we highly recommend you create a specific MS SQL user with + restricted permissions. Check out the{' '} + + Microsoft SQL Server Data Source Docs + {' '} + for more information. + - - + + - + - + - Determines whether or to which extent a secure SSL TCP/IP connection will be negotiated with the server. + + Determines whether or to which extent a secure SSL TCP/IP connection will be negotiated with the server. +
  • - disable - Data sent between client and server is not encrypted. + + {'{{encryptionValue}}'} - Data sent between client and server is not encrypted. +
  • - false - Data sent between client and server is not encrypted beyond the login packet. (default) + + {'{{encryptionValue}}'} - Data sent between client and server is not encrypted beyond the + login packet. (default) +
  • - true - Data sent between client and server is encrypted. + + {'{{encryptionValue}}'} - Data sent between client and server is encrypted. +
- If you're using an older version of Microsoft SQL Server like 2008 and 2008R2 you may need to disable - encryption to be able to connect. + + If you're using an older version of Microsoft SQL Server like 2008 and 2008R2 you may need to + disable encryption to be able to connect. + } - label="Encrypt" + label={t('configuration.configuration-editor.label-encrypt', 'Encrypt')} >
- + - +
  • - SQL Server Authentication This is the default mechanism to connect to MS SQL Server. Enter the - SQL Server Authentication login or the Windows Authentication login in the DOMAIN\User format. + + SQL Server Authentication This is the default mechanism to connect to MS SQL Server. Enter the + SQL Server Authentication login or the Windows Authentication login in the DOMAIN\User format. +
  • - Windows Authentication Windows Integrated Security - single sign on for users who are already - logged onto Windows and have enabled this option for MS SQL Server. + + Windows Authentication Windows Integrated Security - single sign on for users who are already + logged onto Windows and have enabled this option for MS SQL Server. +
  • {azureAuthIsSupported && (
  • - Azure Authentication Securely authenticate and access Azure resources and applications using - Azure AD credentials - Managed Service Identity and Client Secret Credentials are supported. + + Azure Authentication Securely authenticate and access Azure resources and applications using + Azure AD credentials - Managed Service Identity and Client Secret Credentials are supported. +
  • )}
  • - Windows AD: Username + password Windows Active Directory - Sign on for domain user via - username/password. + + Windows AD: Username + password Windows Active Directory - Sign on for domain user via + username/password. +
  • - Windows AD: Keytab Windows Active Directory - Sign on for domain user via keytab file. + + Windows AD: Keytab Windows Active Directory - Sign on for domain user via keytab file. +
  • - Windows AD: Credential cache Windows Active Directory - Sign on for domain user via credential - cache. + + Windows AD: Credential cache Windows Active Directory - Sign on for domain user via credential + cache. +
  • - Windows AD: Credential cache file Windows Active Directory - Sign on for domain user via - credential cache file. + + Windows AD: Credential cache file Windows Active Directory - Sign on for domain user via + credential cache file. +
  • } @@ -292,30 +357,33 @@ export const ConfigurationEditor = (props: DataSourcePluginOptionsEditorProps +
    )} @@ -334,25 +404,37 @@ export const ConfigurationEditor = (props: DataSourcePluginOptionsEditorProps - + - A lower limit for the auto group by time interval. Recommended to be set to write frequency, for example - 1m if your data is written every minute. + + A lower limit for the auto group by time interval. Recommended to be set to write frequency, for + example + {'{{exampleInterval}}'} if your data is written every minute. + } - label="Min time interval" + label={t('configuration.configuration-editor.label-min-interval', 'Min time interval')} > - The number of seconds to wait before canceling the request when connecting to the database. The default - is 0, meaning no timeout. + + The number of seconds to wait before canceling the request when connecting to the database. The + default is {'{{defaultTimeout}}'}, meaning no timeout. + } - label="Connection timeout" + label={t('configuration.configuration-editor.label-connection-timeout', 'Connection timeout')} > - Use the format user@EXAMPLE.COM. Realm is derived from the username. + + Use the format user@EXAMPLE.COM. Realm is derived from the username. + ); export const KerberosConfig = (props: DataSourcePluginOptionsEditorProps) => { const { options: settings, onOptionsChange } = props; + const { t } = useTranslate(); const jsonData = settings.jsonData; const LONG_WIDTH = 40; @@ -36,23 +40,29 @@ export const KerberosConfig = (props: DataSourcePluginOptionsEditorProps {jsonData.authenticationType === MSSQLAuthenticationType.kerberosKeytab && ( -
    +
    onOptionsChange({ ...settings, ...{ ['user']: e.currentTarget.value } })} width={LONG_WIDTH} /> - + +
    +
    onOptionsChange({ ...settings, ...{ ['user']: e.currentTarget.value } })} width={LONG_WIDTH} /> ) => { const { options: settings } = props; + const { t } = useTranslate(); const jsonData = settings.jsonData; const configFilePath = jsonData?.configFilePath; const LONG_WIDTH = 40; @@ -137,19 +158,28 @@ export const KerberosAdvancedSettings = (props: DataSourcePluginOptionsEditorPro return ( <> - +
    - The default is 1 and means always use TCP and is optional. + + The default is {'{{default}}'} and means always use TCP and is optional. + } > { @@ -161,31 +191,42 @@ export const KerberosAdvancedSettings = (props: DataSourcePluginOptionsEditorPro /> - Indicate whether DNS `SRV` records should be used to locate the KDCs and other servers for a realm. The - default is true. + + Indicate whether DNS `SRV` records should be used to locate the KDCs and other servers for a realm. + The default is {'{{default}}'}. + } > - The path to the configuration file for the{' '} - - MIT krb5 package - - . The default is /etc/krb5.conf. + + The path to the configuration file for the{' '} + + MIT krb5 package + + . The default is {'{{default}}'}. + } > diff --git a/public/app/plugins/datasource/mssql/locales/en-US/mssql.json b/public/app/plugins/datasource/mssql/locales/en-US/mssql.json new file mode 100644 index 00000000000..7311bb0add3 --- /dev/null +++ b/public/app/plugins/datasource/mssql/locales/en-US/mssql.json @@ -0,0 +1,128 @@ +{ + "azureauth": { + "azure-credentials-form": { + "aria-label-application-client-id": "Application Client ID", + "aria-label-azure-cloud": "Azure Cloud", + "aria-label-client-secret": "Client Secret", + "aria-label-configured-client-secret": "Client Secret", + "aria-label-password": "Password", + "aria-label-password-configured": "Password", + "aria-label-tenant-id": "Tenant ID", + "aria-label-user-id": "User ID", + "arialabel-client-id": "Client ID", + "auth-options-app-registration": "App Registration", + "auth-options-azure-entra": "Azure Entra Password", + "auth-options-managed-identity": "Managed Identity", + "client-secret-reset": "Reset", + "description-authentication": "Choose the type of authentication to Azure services", + "label-application-client-id": "Application Client ID", + "label-authentication": "Authentication", + "label-azure-cloud": "Azure Cloud", + "label-client-id": "Application (client) ID", + "label-client-secret": "Client Secret", + "label-configured-client-secret": "Client Secret", + "label-password": "Password", + "label-password-configured": "Password", + "label-tenant-id": "Directory (tenant) ID", + "label-user-id": "User Id", + "password-reset": "Reset", + "placeholder-configured-client-secret": "configured", + "placeholder-password-configured": "configured", + "required-application-client-id": "Application Client ID is required", + "required-client-id": "Client ID is required", + "required-client-secret": "Client secret is required", + "required-password": "Password is required", + "required-tenant-id": "Tenant ID is required" + } + }, + "cheat-sheet": { + "condtional-macros": "Or build your own conditionals using these macros which just return the values:", + "example-time-group": "Example of group by and order by with {{timeGroupMacro}}:", + "fillvalue": "by setting fillvalue Grafana will fill in missing values according to the interval. fillvalue can be either a literal value, {{null}} or {{previous}}; {{previous}} will fill in the previous seen value or {{null}} if none has been seen yet", + "macros": "Macros:", + "optional": "Optional:", + "optional-tip": "return column named <1>{{columnName}} to represent the series name.", + "optional-tip-2": "If multiple value columns are returned the {{columnName}} column is used as prefix.", + "optional-tip-3": "If no column named {{columnName}} is found the column name of the value column is used as series name", + "resultsets-time-sorted": "Resultsets of time series queries need to be sorted by time.", + "table": "Table:", + "table-tip": "return any set of columns", + "time-series": "Time series:", + "time-series-tip": "return column named time (in UTC), as a unix time stamp or any sql native date data type. You can use the macros below.", + "time-series-tip-2": "any other columns returned will be the time point values.", + "title": "MSSQL cheat sheet" + }, + "configuration": { + "configuration-editor": { + "body-user-permission": "The database user should only be granted {{permissionType}} permissions on the specified database and tables you want to query. Grafana does not validate that queries are safe so queries can contain any SQL statement. For example, statements like <3>{{example1}} and <5>{{example2}} would be executed. To protect against this we <7>highly recommend you create a specific MS SQL user with restricted permissions. Check out the <10>Microsoft SQL Server Data Source Docs for more information.", + "description-additional-settings": "Additional settings are optional settings that can be configured for more control over your data source. This includes connection limits, connection timeout, group-by time interval, and Secure Socks Proxy.", + "description-auth-type-azure-auth": "<0>Azure Authentication Securely authenticate and access Azure resources and applications using Azure AD credentials - Managed Service Identity and Client Secret Credentials are supported.", + "description-auth-type-credential-cache": "<0>Windows AD: Credential cache Windows Active Directory - Sign on for domain user via credential cache.", + "description-auth-type-credential-cache-file": "<0>Windows AD: Credential cache file Windows Active Directory - Sign on for domain user via credential cache file.", + "description-auth-type-keytab": "<0>Windows AD: Keytab Windows Active Directory - Sign on for domain user via keytab file.", + "description-auth-type-sql-server": "<0>SQL Server Authentication This is the default mechanism to connect to MS SQL Server. Enter the SQL Server Authentication login or the Windows Authentication login in the DOMAIN\\User format.", + "description-auth-type-username-password": "<0>Windows AD: Username + password Windows Active Directory - Sign on for domain user via username/password.", + "description-auth-type-windows-auth": "<0>Windows Authentication Windows Integrated Security - single sign on for users who are already logged onto Windows and have enabled this option for MS SQL Server.", + "description-connection-timeout": "The number of seconds to wait before canceling the request when connecting to the database. The default is <1>{{defaultTimeout}}, meaning no timeout.", + "description-encrypt": "Determines whether or to which extent a secure SSL TCP/IP connection will be negotiated with the server.", + "description-encrypt-disable": "<0>{{encryptionValue}} - Data sent between client and server is not encrypted.", + "description-encrypt-false": "<0>{{encryptionValue}} - Data sent between client and server is not encrypted beyond the login packet. (default)", + "description-encrypt-older-version": "If you're using an older version of Microsoft SQL Server like 2008 and 2008R2 you may need to disable encryption to be able to connect.", + "description-encrypt-true": "<0>{{encryptionValue}} - Data sent between client and server is encrypted.", + "description-min-interval": "A lower limit for the auto group by time interval. Recommended to be set to write frequency, for example<1>{{exampleInterval}} if your data is written every minute.", + "description-tls-cert": "Path to file containing the public key certificate of the CA that signed the SQL Server certificate. Needed when the server certificate is self signed.", + "label-auth-settings": "Azure Authentication Settings", + "label-auth-type": "Authentication Type", + "label-common-name": "Hostname in server certificate", + "label-connection-timeout": "Connection timeout", + "label-encrypt": "Encrypt", + "label-min-interval": "Min time interval", + "label-password": "Password", + "label-skip-tls": "Skip TLS Verify", + "label-tls-cert": "TLS/SSL Root Certificate", + "label-username": "Username", + "placeholder-common-name": "Common Name (CN) in server certificate", + "placeholder-database": "database name", + "placeholder-password": "Password", + "placeholder-tls-cert": "TLS/SSL root certificate file path", + "placeholder-user": "user", + "required-database": "Database is required", + "required-host": "Host is required", + "required-password": "Password is required", + "required-username": "Username is required", + "title-additional-settings": "Additional settings", + "title-authentication": "Authentication", + "title-connection": "Connection", + "title-connection-details": "Connection details", + "title-database": "Database", + "title-host": "Host", + "title-tls-auth": "TLS/SSL Auth", + "title-user-permission": "User Permission" + }, + "kerberos": { + "username-message": "Use the format <1>user@EXAMPLE.COM. Realm is derived from the username." + }, + "kerberos-advanced-settings": { + "description-dns-lookup-kdc": "Indicate whether DNS `SRV` records should be used to locate the KDCs and other servers for a realm. The default is <1>{{default}}.", + "description-krb5-config-file-path": "The path to the configuration file for the <2>MIT krb5 package. The default is <4>{{default}}.", + "description-udp-preference-limit": "The default is <1>{{default}} and means always use TCP and is optional.", + "label-dns-lookup-kdc": "DNS Lookup KDC", + "label-krb5-config-file-path": "krb5 config file path", + "label-udp-preference-limit": "UDP Preference Limit", + "title-advanced-settings": "Windows AD: Advanced Settings" + }, + "kerberos-config": { + "label-credential-cache": "Windows AD: Credential cache", + "label-credential-cache-file": "Windows AD: Credential cache file", + "label-credential-cache-file-path": "Credential cache file path", + "label-credential-cache-path": "Credential cache path", + "label-keytab": "Windows AD: Keytab", + "label-keytab-file-path": "Keytab file path", + "label-username": "Username", + "placeholder-username": "name@EXAMPLE.COM", + "required-credential-cache-file-path": "Credential cache file path is required", + "required-credential-cache-path": "Credential cache path is required", + "required-username": "Username is required" + } + } +} diff --git a/public/app/plugins/datasource/mssql/locales/i18next-parser.config.cjs b/public/app/plugins/datasource/mssql/locales/i18next-parser.config.cjs new file mode 100644 index 00000000000..26140245bab --- /dev/null +++ b/public/app/plugins/datasource/mssql/locales/i18next-parser.config.cjs @@ -0,0 +1,12 @@ +module.exports = { + locales: ['en-US'], // Only en-US is updated - Crowdin will PR with other languages + sort: true, + createOldCatalogs: false, + failOnWarnings: true, + verbose: false, + resetDefaultValueLocale: 'en-US', // Updates extracted values when they change in code + + defaultNamespace: 'mssql', + input: ['../**/*.{tsx,ts}'], + output: './locales/$LOCALE/$NAMESPACE.json', +}; diff --git a/public/app/plugins/datasource/mssql/module.ts b/public/app/plugins/datasource/mssql/module.ts index 82c73c4b932..69e21d12c3d 100644 --- a/public/app/plugins/datasource/mssql/module.ts +++ b/public/app/plugins/datasource/mssql/module.ts @@ -1,11 +1,15 @@ import { DataSourcePlugin } from '@grafana/data'; +import { initPluginTranslations } from '@grafana/i18n'; import { SQLQuery, SqlQueryEditorLazy } from '@grafana/sql'; import { CheatSheet } from './CheatSheet'; import { ConfigurationEditor } from './configuration/ConfigurationEditor'; import { MssqlDatasource } from './datasource'; +import pluginJson from './plugin.json'; import { MssqlOptions } from './types'; +initPluginTranslations(pluginJson.id); + export const plugin = new DataSourcePlugin(MssqlDatasource) .setQueryEditor(SqlQueryEditorLazy) .setQueryEditorHelp(CheatSheet) diff --git a/public/app/plugins/datasource/mssql/package.json b/public/app/plugins/datasource/mssql/package.json index 2b975ac9ad9..03aab4a3eac 100644 --- a/public/app/plugins/datasource/mssql/package.json +++ b/public/app/plugins/datasource/mssql/package.json @@ -6,6 +6,7 @@ "dependencies": { "@emotion/css": "11.13.5", "@grafana/data": "12.1.0-pre", + "@grafana/i18n": "12.1.0-pre", "@grafana/plugin-ui": "0.10.5", "@grafana/runtime": "12.1.0-pre", "@grafana/sql": "12.1.0-pre", @@ -25,6 +26,7 @@ "@types/lodash": "4.17.15", "@types/node": "22.12.0", "@types/react": "18.3.18", + "i18next-parser": "9.3.0", "ts-node": "10.9.2", "typescript": "5.7.3", "webpack": "5.97.1" @@ -35,7 +37,8 @@ "scripts": { "build": "webpack -c ./webpack.config.ts --env production", "build:commit": "webpack -c ./webpack.config.ts --env production --env commit=$(git rev-parse --short HEAD)", - "dev": "webpack -w -c ./webpack.config.ts --env development" + "dev": "webpack -w -c ./webpack.config.ts --env development", + "i18n-extract": "i18next --config locales/i18next-parser.config.cjs" }, "packageManager": "yarn@4.6.0" } diff --git a/public/app/plugins/datasource/mssql/plugin.json b/public/app/plugins/datasource/mssql/plugin.json index 0d704a8354b..9cca0bb544e 100644 --- a/public/app/plugins/datasource/mssql/plugin.json +++ b/public/app/plugins/datasource/mssql/plugin.json @@ -35,5 +35,26 @@ "queryOptions": { "minInterval": true - } + }, + "languages": [ + "en-US", + "fr-FR", + "es-ES", + "de-DE", + "pt-BR", + "zh-Hans", + "it-IT", + "ja-JP", + "id-ID", + "ko-KR", + "ru-RU", + "cs-CZ", + "nl-NL", + "hu-HU", + "pt-PT", + "pl-PL", + "sv-SE", + "tr-TR", + "zh-Hant" + ] } diff --git a/public/app/plugins/datasource/mssql/webpack.config.ts b/public/app/plugins/datasource/mssql/webpack.config.ts index 55a880fef5c..2e981f9ea7c 100644 --- a/public/app/plugins/datasource/mssql/webpack.config.ts +++ b/public/app/plugins/datasource/mssql/webpack.config.ts @@ -1,4 +1,14 @@ -import config from '@grafana/plugin-configs/webpack.config'; +import type { Configuration } from 'webpack'; +import { merge } from 'webpack-merge'; + +import grafanaConfig from '@grafana/plugin-configs/webpack.config'; + +const config = async (env: Record): Promise => { + const baseConfig = await grafanaConfig(env); + + return merge(baseConfig, { + externals: ['i18next'], + }); +}; -// eslint-disable-next-line no-barrel-files/no-barrel-files export default config; diff --git a/yarn.lock b/yarn.lock index 20b60a87324..9d03d4203ab 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2685,6 +2685,7 @@ __metadata: "@emotion/css": "npm:11.13.5" "@grafana/data": "npm:12.1.0-pre" "@grafana/e2e-selectors": "npm:12.1.0-pre" + "@grafana/i18n": "npm:12.1.0-pre" "@grafana/plugin-configs": "npm:12.1.0-pre" "@grafana/plugin-ui": "npm:0.10.5" "@grafana/runtime": "npm:12.1.0-pre" @@ -2697,6 +2698,7 @@ __metadata: "@types/lodash": "npm:4.17.15" "@types/node": "npm:22.12.0" "@types/react": "npm:18.3.18" + i18next-parser: "npm:9.3.0" lodash: "npm:4.17.21" react: "npm:18.3.1" rxjs: "npm:7.8.1"