From 6ce2fac2bb3fff75de41a84a06c56c56646d2ef2 Mon Sep 17 00:00:00 2001 From: Ashley Harrison Date: Mon, 7 Jul 2025 11:30:11 +0100 Subject: [PATCH] Internationalisation: Mark up `geomap` panel edit options (#107140) mark up geomap panel edit options --- .../editors/ScaleDimensionEditor.tsx | 15 +-- .../app/features/geo/editor/locationEditor.ts | 21 ++-- .../geo/editor/locationModeEditor.tsx | 61 ++++++----- public/app/features/geo/utils/location.ts | 13 +-- .../panel/geomap/editor/StyleEditor.tsx | 27 +++-- .../panel/geomap/editor/layerEditor.tsx | 13 +-- .../panel/geomap/layers/data/markersLayer.tsx | 7 +- public/app/plugins/panel/geomap/module.tsx | 62 ++++++----- .../app/plugins/panel/geomap/utils/utils.ts | 5 +- public/locales/en-US/grafana.json | 102 +++++++++++++++++- 10 files changed, 235 insertions(+), 91 deletions(-) diff --git a/public/app/features/dimensions/editors/ScaleDimensionEditor.tsx b/public/app/features/dimensions/editors/ScaleDimensionEditor.tsx index f2b69690c62..098ac6e038b 100644 --- a/public/app/features/dimensions/editors/ScaleDimensionEditor.tsx +++ b/public/app/features/dimensions/editors/ScaleDimensionEditor.tsx @@ -11,16 +11,19 @@ import { NumberInput } from 'app/core/components/OptionsUI/NumberInput'; import { validateScaleOptions, validateScaleConfig } from '../scale'; import { ScaleDimensionOptions } from '../types'; -const fixedValueOption: SelectableValue = { - label: 'Fixed value', - value: '_____fixed_____', -}; - export const ScaleDimensionEditor = (props: StandardEditorProps) => { const { value, context, onChange, item } = props; const { settings } = item; const styles = useStyles2(getStyles); + const fixedValueOption: SelectableValue = useMemo( + () => ({ + label: t('dimensions.scale-dimension-editor.fixed-value-option.label.fixed-value', 'Fixed value'), + value: '_____fixed_____', + }), + [] + ); + const fieldName = value?.field; const isFixed = Boolean(!fieldName); const names = useFieldDisplayNames(context.data); @@ -53,7 +56,7 @@ export const ScaleDimensionEditor = (props: StandardEditorProps( builder.addCustomEditor({ id: 'modeEditor', path: `${prefix}mode`, - name: 'Location Mode', + name: t('geo.location-editor.name-location-mode', 'Location Mode'), editor: LocationModeEditor, settings: { data, source }, }); @@ -25,18 +26,18 @@ export function addLocationFields( builder .addFieldNamePicker({ path: `${prefix}latitude`, - name: 'Latitude field', + name: t('geo.location-editor.name-latitude-field', 'Latitude field'), settings: { filter: (f: Field) => f.type === FieldType.number, - noFieldsMessage: 'No numeric fields found', + noFieldsMessage: t('geo.location-editor.latitude-field.no-fields-message', 'No numeric fields found'), }, }) .addFieldNamePicker({ path: `${prefix}longitude`, - name: 'Longitude field', + name: t('geo.location-editor.name-longitude-field', 'Longitude field'), settings: { filter: (f: Field) => f.type === FieldType.number, - noFieldsMessage: 'No numeric fields found', + noFieldsMessage: t('geo.location-editor.longitude-field.no-fields-message', 'No numeric fields found'), }, }); break; @@ -44,10 +45,10 @@ export function addLocationFields( case FrameGeometrySourceMode.Geohash: builder.addFieldNamePicker({ path: `${prefix}geohash`, - name: 'Geohash field', + name: t('geo.location-editor.name-geohash-field', 'Geohash field'), settings: { filter: (f: Field) => f.type === FieldType.string, - noFieldsMessage: 'No strings fields found', + noFieldsMessage: t('geo.location-editor.geohash-field.no-fields-message', 'No strings fields found'), }, }); break; @@ -56,16 +57,16 @@ export function addLocationFields( builder .addFieldNamePicker({ path: `${prefix}lookup`, - name: 'Lookup field', + name: t('geo.location-editor.name-lookup-field', 'Lookup field'), settings: { filter: (f: Field) => f.type === FieldType.string, - noFieldsMessage: 'No strings fields found', + noFieldsMessage: t('geo.location-editor.lookup-field.no-fields-message', 'No strings fields found'), }, }) .addCustomEditor({ id: 'gazetteer', path: `${prefix}gazetteer`, - name: 'Gazetteer', + name: t('geo.location-editor.name-gazetteer', 'Gazetteer'), editor: GazetteerPathEditor, }); } diff --git a/public/app/features/geo/editor/locationModeEditor.tsx b/public/app/features/geo/editor/locationModeEditor.tsx index 6ded40a3abe..aacc913123c 100644 --- a/public/app/features/geo/editor/locationModeEditor.tsx +++ b/public/app/features/geo/editor/locationModeEditor.tsx @@ -3,38 +3,12 @@ import { useEffect, useState } from 'react'; import { StandardEditorProps, DataFrame, GrafanaTheme2 } from '@grafana/data'; import { selectors } from '@grafana/e2e-selectors'; +import { t } from '@grafana/i18n'; import { FrameGeometrySource, FrameGeometrySourceMode } from '@grafana/schema'; import { Alert, HorizontalGroup, Icon, Select, useStyles2 } from '@grafana/ui'; import { FrameGeometryField, getGeometryField, getLocationMatchers } from '../utils/location'; -const MODE_OPTIONS = [ - { - value: FrameGeometrySourceMode.Auto, - label: 'Auto', - ariaLabel: selectors.components.Transforms.SpatialOperations.location.autoOption, - description: 'Automatically identify location data based on default field names', - }, - { - value: FrameGeometrySourceMode.Coords, - label: 'Coords', - ariaLabel: selectors.components.Transforms.SpatialOperations.location.coords.option, - description: 'Specify latitude and longitude fields', - }, - { - value: FrameGeometrySourceMode.Geohash, - label: 'Geohash', - ariaLabel: selectors.components.Transforms.SpatialOperations.location.geohash.option, - description: 'Specify geohash field', - }, - { - value: FrameGeometrySourceMode.Lookup, - label: 'Lookup', - ariaLabel: selectors.components.Transforms.SpatialOperations.location.lookup.option, - description: 'Specify Gazetteer and lookup field', - }, -]; - interface ModeEditorSettings { data?: DataFrame[]; source?: FrameGeometrySource; @@ -50,6 +24,39 @@ export const LocationModeEditor = ({ }: StandardEditorProps) => { const [info, setInfo] = useState(); + const MODE_OPTIONS = [ + { + value: FrameGeometrySourceMode.Auto, + label: t('geo.location-more-editor.mode-options.label-auto', 'Auto'), + ariaLabel: selectors.components.Transforms.SpatialOperations.location.autoOption, + description: t( + 'geo.location-more-editor.mode-options.description-auto', + 'Automatically identify location data based on default field names' + ), + }, + { + value: FrameGeometrySourceMode.Coords, + label: t('geo.location-more-editor.mode-options.label-coords', 'Coords'), + ariaLabel: selectors.components.Transforms.SpatialOperations.location.coords.option, + description: t( + 'geo.location-more-editor.mode-options.description-coords', + 'Specify latitude and longitude fields' + ), + }, + { + value: FrameGeometrySourceMode.Geohash, + label: t('geo.location-more-editor.mode-options.label-geohash', 'Geohash'), + ariaLabel: selectors.components.Transforms.SpatialOperations.location.geohash.option, + description: t('geo.location-more-editor.mode-options.description-geohash', 'Specify geohash field'), + }, + { + value: FrameGeometrySourceMode.Lookup, + label: t('geo.location-more-editor.mode-options.label-lookup', 'Lookup'), + ariaLabel: selectors.components.Transforms.SpatialOperations.location.lookup.option, + description: t('geo.location-more-editor.mode-options.description-lookup', 'Specify Gazetteer and lookup field'), + }, + ]; + useEffect(() => { if (item.settings?.source && item.settings?.data?.length && item.settings.data[0]) { getLocationMatchers(item.settings.source).then((location) => { diff --git a/public/app/features/geo/utils/location.ts b/public/app/features/geo/utils/location.ts index 91f009d54b6..96e92929cdd 100644 --- a/public/app/features/geo/utils/location.ts +++ b/public/app/features/geo/utils/location.ts @@ -9,6 +9,7 @@ import { getFieldDisplayName, FieldType, } from '@grafana/data'; +import { t } from '@grafana/i18n'; import { FrameGeometrySource, FrameGeometrySourceMode } from '@grafana/schema'; import { getGeoFieldFromGazetteer, pointFieldFromGeohash, pointFieldFromLonLat } from '../format/utils'; @@ -178,7 +179,7 @@ export function getGeometryField(frame: DataFrame, location: LocationFieldMatche }; } return { - warning: 'Unable to find location fields', + warning: t('geo.get-geometry-field.warning-unable-to-find', 'Unable to find location fields'), }; case FrameGeometrySourceMode.Coords: @@ -190,7 +191,7 @@ export function getGeometryField(frame: DataFrame, location: LocationFieldMatche }; } return { - warning: 'Select latitude/longitude fields', + warning: t('geo.get-geometry-field.warning-select-lat-long', 'Select latitude/longitude fields'), }; case FrameGeometrySourceMode.Geohash: @@ -202,7 +203,7 @@ export function getGeometryField(frame: DataFrame, location: LocationFieldMatche }; } return { - warning: 'Select geohash field', + warning: t('geo.get-geometry-field.warning-select-geohash', 'Select geohash field'), }; case FrameGeometrySourceMode.Lookup: @@ -215,13 +216,13 @@ export function getGeometryField(frame: DataFrame, location: LocationFieldMatche }; } return { - warning: 'Gazetteer not found', + warning: t('geo.get-geometry-field.warning-gazetteer-not-found', 'Gazetteer not found'), }; } return { - warning: 'Select lookup field', + warning: t('geo.get-geometry-field.warning-select-lookup', 'Select lookup field'), }; } - return { warning: 'unable to find geometry' }; + return { warning: t('geo.get-geometry-field.warning-no-geometry', 'unable to find geometry') }; } diff --git a/public/app/plugins/panel/geomap/editor/StyleEditor.tsx b/public/app/plugins/panel/geomap/editor/StyleEditor.tsx index c5c55c8de49..517ba553513 100644 --- a/public/app/plugins/panel/geomap/editor/StyleEditor.tsx +++ b/public/app/plugins/panel/geomap/editor/StyleEditor.tsx @@ -242,9 +242,15 @@ export const StyleEditor = (props: Props) => { value={value?.symbolAlign?.vertical ?? defaultStyleConfig.symbolAlign.vertical} onChange={onAlignVerticalChange} options={[ - { value: VerticalAlign.Top, label: capitalize(VerticalAlign.Top) }, - { value: VerticalAlign.Center, label: capitalize(VerticalAlign.Center) }, - { value: VerticalAlign.Bottom, label: capitalize(VerticalAlign.Bottom) }, + { value: VerticalAlign.Top, label: t('geomap.style-editor.vertical-align-options.label-top', 'Top') }, + { + value: VerticalAlign.Center, + label: t('geomap.style-editor.vertical-align-options.label-center', 'Center'), + }, + { + value: VerticalAlign.Bottom, + label: t('geomap.style-editor.vertical-align-options.label-bottom', 'Bottom'), + }, ]} /> @@ -253,9 +259,18 @@ export const StyleEditor = (props: Props) => { value={value?.symbolAlign?.horizontal ?? defaultStyleConfig.symbolAlign.horizontal} onChange={onAlignHorizontalChange} options={[ - { value: HorizontalAlign.Left, label: capitalize(HorizontalAlign.Left) }, - { value: HorizontalAlign.Center, label: capitalize(HorizontalAlign.Center) }, - { value: HorizontalAlign.Right, label: capitalize(HorizontalAlign.Right) }, + { + value: HorizontalAlign.Left, + label: t('geomap.style-editor.horizontal-align-options.label-left', 'Left'), + }, + { + value: HorizontalAlign.Center, + label: t('geomap.style-editor.horizontal-align-options.label-center', 'Center'), + }, + { + value: HorizontalAlign.Right, + label: t('geomap.style-editor.horizontal-align-options.label-right', 'Right'), + }, ]} /> diff --git a/public/app/plugins/panel/geomap/editor/layerEditor.tsx b/public/app/plugins/panel/geomap/editor/layerEditor.tsx index 865b9f94654..4f70a82e587 100644 --- a/public/app/plugins/panel/geomap/editor/layerEditor.tsx +++ b/public/app/plugins/panel/geomap/editor/layerEditor.tsx @@ -2,6 +2,7 @@ import { get as lodashGet, isEqual } from 'lodash'; import { FrameGeometrySourceMode, getFrameMatchers, MapLayerOptions } from '@grafana/data'; import { NestedPanelOptions, NestedValueAccess } from '@grafana/data/internal'; +import { t } from '@grafana/i18n'; import { setOptionImmutably } from 'app/features/dashboard/components/PanelEditor/utils'; import { addLocationFields } from 'app/features/geo/editor/locationEditor'; @@ -69,7 +70,7 @@ export function getLayerEditor(opts: LayerEditorOptions): NestedPanelOptions = { .addCustomEditor({ id: 'config.style', path: 'config.style', - name: 'Styles', + name: t('geomap.markers-layer.name-styles', 'Styles'), editor: StyleEditor, settings: { displayRotation: true, @@ -239,8 +240,8 @@ export const markersLayer: MapLayerRegistryItem = { }) .addBooleanSwitch({ path: 'config.showLegend', - name: 'Show legend', - description: 'Show map legend', + name: t('geomap.markers-layer.name-show-legend', 'Show legend'), + description: t('geomap.markers-layer.description-show-legend', 'Show map legend'), defaultValue: defaultOptions.showLegend, }); }, diff --git a/public/app/plugins/panel/geomap/module.tsx b/public/app/plugins/panel/geomap/module.tsx index b5376ea7acf..f8c7825f896 100644 --- a/public/app/plugins/panel/geomap/module.tsx +++ b/public/app/plugins/panel/geomap/module.tsx @@ -1,5 +1,5 @@ import { PanelPlugin } from '@grafana/data'; -import { Trans } from '@grafana/i18n'; +import { t, Trans } from '@grafana/i18n'; import { config } from '@grafana/runtime'; import { commonOptionsBuilder } from '@grafana/ui'; @@ -20,13 +20,13 @@ export const plugin = new PanelPlugin(GeomapPanel) }, }) .setPanelOptions((builder, context) => { - let category = ['Map view']; + let category = [t('geomap.category-map-view', 'Map view')]; builder.addCustomEditor({ category, id: 'view', path: 'view', - name: 'Initial view', // don't show it - description: 'This location will show when the panel first loads.', + name: t('geomap.name-initial-view', 'Initial view'), // don't show it + description: t('geomap.description-initial-view', 'This location will show when the panel first loads.'), editor: MapViewEditor, defaultValue: defaultMapViewConfig, }); @@ -34,8 +34,11 @@ export const plugin = new PanelPlugin(GeomapPanel) builder.addBooleanSwitch({ category, path: 'view.shared', - description: 'Use the same view across multiple panels. Note: this may require a dashboard reload.', - name: 'Share view', + description: t( + 'geomap.description-share-view', + 'Use the same view across multiple panels. Note: this may require a dashboard reload.' + ), + name: t('geomap.name-share-view', 'Share view'), defaultValue: defaultMapViewConfig.shared, }); @@ -44,8 +47,8 @@ export const plugin = new PanelPlugin(GeomapPanel) if (!state?.layers) { // TODO? show spinner? } else { - const layersCategory = ['Map layers']; - const basemapCategory = ['Basemap layer']; + const layersCategory = [t('geomap.category-map-layers', 'Map layers')]; + const basemapCategory = [t('geomap.category-basemap-layer', 'Basemap layer')]; builder.addCustomEditor({ category: layersCategory, id: 'layers', @@ -93,59 +96,70 @@ export const plugin = new PanelPlugin(GeomapPanel) } // The controls section - category = ['Map controls']; + category = [t('geomap.category-map-controls', 'Map controls')]; builder .addBooleanSwitch({ category, path: 'controls.showZoom', - description: 'Show zoom control buttons in the upper left corner', - name: 'Show zoom control', + description: t('geomap.description-show-zoom', 'Show zoom control buttons in the upper left corner'), + name: t('geomap.name-show-zoom', 'Show zoom control'), defaultValue: true, }) .addBooleanSwitch({ category, path: 'controls.mouseWheelZoom', - description: 'Enable zoom control via mouse wheel', - name: 'Mouse wheel zoom', + description: t('geomap.description-mouse-wheel-zoom', 'Enable zoom control via mouse wheel'), + name: t('geomap.name-mouse-wheel-zoom', 'Mouse wheel zoom'), defaultValue: true, }) .addBooleanSwitch({ category, path: 'controls.showAttribution', - name: 'Show attribution', - description: 'Show the map source attribution info in the lower right', + name: t('geomap.name-show-attribution', 'Show attribution'), + description: t( + 'geomap.description-show-attribution', + 'Show the map source attribution info in the lower right' + ), defaultValue: true, }) .addBooleanSwitch({ category, path: 'controls.showScale', - name: 'Show scale', - description: 'Indicate map scale', + name: t('geomap.name-show-scale', 'Show scale'), + description: t('geomap.description-show-scale', 'Indicate map scale'), defaultValue: false, }) .addBooleanSwitch({ category, path: 'controls.showMeasure', - name: 'Show measure tools', - description: 'Show tools for making measurements on the map', + name: t('geomap.name-show-measure', 'Show measure tools'), + description: t('geomap.description-show-measure', 'Show tools for making measurements on the map'), defaultValue: false, }) .addBooleanSwitch({ category, path: 'controls.showDebug', - name: 'Show debug', - description: 'Show map info', + name: t('geomap.name-show-debug', 'Show debug'), + description: t('geomap.description-show-debug', 'Show map info'), defaultValue: false, }) .addRadio({ category, path: 'tooltip.mode', - name: 'Tooltip', + name: t('geomap.name-tooltip', 'Tooltip'), defaultValue: TooltipMode.Details, settings: { options: [ - { label: 'None', value: TooltipMode.None, description: 'Show contents on click, not hover' }, - { label: 'Details', value: TooltipMode.Details, description: 'Show popup on hover' }, + { + label: t('geomap.tooltip-options.label-none', 'None'), + value: TooltipMode.None, + description: t('geomap.tooltip-options.description-none', 'Show contents on click, not hover'), + }, + { + label: t('geomap.tooltip-options.label-details', 'Details'), + value: TooltipMode.Details, + description: t('geomap.tooltip-options.description-details', 'Show popup on hover'), + }, ], }, }); diff --git a/public/app/plugins/panel/geomap/utils/utils.ts b/public/app/plugins/panel/geomap/utils/utils.ts index 721b57abb87..615466f339a 100644 --- a/public/app/plugins/panel/geomap/utils/utils.ts +++ b/public/app/plugins/panel/geomap/utils/utils.ts @@ -14,6 +14,7 @@ import TileSource from 'ol/source/Tile'; import VectorSource from 'ol/source/Vector'; import { DataFrame, GrafanaTheme2, SelectableValue } from '@grafana/data'; +import { t } from '@grafana/i18n'; import { getTemplateSrv } from '@grafana/runtime'; import { getColorDimension } from 'app/features/dimensions/color'; import { getScalarDimension } from 'app/features/dimensions/scalar'; @@ -132,13 +133,13 @@ export const notifyPanelEditor = (geomapPanel: GeomapPanel, layers: MapLayerStat export const getNextLayerName = (panel: GeomapPanel) => { let idx = panel.layers.length; // since basemap is 0, this looks right while (true && idx < 100) { - const name = `Layer ${idx++}`; + const name = t('geomap.utils.get-next-layer-name', 'Layer {{name}}', { name: idx++ }); if (!panel.byName.has(name)) { return name; } } - return `Layer ${Date.now()}`; + return t('geomap.utils.get-next-layer-name', 'Layer {{name}}', { name: Date.now() }); }; export function isSegmentVisible( diff --git a/public/locales/en-US/grafana.json b/public/locales/en-US/grafana.json index 9eb177b113c..4ee07cfc845 100644 --- a/public/locales/en-US/grafana.json +++ b/public/locales/en-US/grafana.json @@ -6310,6 +6310,11 @@ } }, "scale-dimension-editor": { + "fixed-value-option": { + "label": { + "fixed-value": "Fixed value" + } + }, "label-max": "Max", "label-min": "Min", "label-value": "Value" @@ -7159,7 +7164,53 @@ "incomplete-request-error": "Sorry, I was unable to complete your request. Please try again.", "send-custom-feedback": "Send" }, + "geo": { + "get-geometry-field": { + "warning-gazetteer-not-found": "Gazetteer not found", + "warning-no-geometry": "unable to find geometry", + "warning-select-geohash": "Select geohash field", + "warning-select-lat-long": "Select latitude/longitude fields", + "warning-select-lookup": "Select lookup field", + "warning-unable-to-find": "Unable to find location fields" + }, + "location-editor": { + "geohash-field": { + "no-fields-message": "No strings fields found" + }, + "latitude-field": { + "no-fields-message": "No numeric fields found" + }, + "longitude-field": { + "no-fields-message": "No numeric fields found" + }, + "lookup-field": { + "no-fields-message": "No strings fields found" + }, + "name-gazetteer": "Gazetteer", + "name-geohash-field": "Geohash field", + "name-latitude-field": "Latitude field", + "name-location-mode": "Location Mode", + "name-longitude-field": "Longitude field", + "name-lookup-field": "Lookup field" + }, + "location-more-editor": { + "mode-options": { + "description-auto": "Automatically identify location data based on default field names", + "description-coords": "Specify latitude and longitude fields", + "description-geohash": "Specify geohash field", + "description-lookup": "Specify Gazetteer and lookup field", + "label-auto": "Auto", + "label-coords": "Coords", + "label-geohash": "Geohash", + "label-lookup": "Lookup" + } + } + }, "geomap": { + "category-basemap-layer": "Basemap layer", + "category-map-controls": "Map controls", + "category-map-layers": "Map layers", + "category-map-view": "Map view", "coordinates-map-view-editor": { "label-latitude": "Latitude", "label-longitude": "Longitude" @@ -7168,6 +7219,14 @@ "center": "Center:", "zoom": "Zoom:" }, + "description-initial-view": "This location will show when the panel first loads.", + "description-mouse-wheel-zoom": "Enable zoom control via mouse wheel", + "description-share-view": "Use the same view across multiple panels. Note: this may require a dashboard reload.", + "description-show-attribution": "Show the map source attribution info in the lower right", + "description-show-debug": "Show map info", + "description-show-measure": "Show tools for making measurements on the map", + "description-show-scale": "Indicate map scale", + "description-show-zoom": "Show zoom control buttons in the upper left corner", "fit-map-view-editor": { "all-layers-editor-fragment": { "label-layer": "Layer" @@ -7190,6 +7249,14 @@ "geomap-style-rules-editor": { "aria-label-add-geomap-style-rule": "Add geomap style rule" }, + "layer-editor": { + "category-base-layer": "Base layer", + "description-display-tooltip": "Show the tooltip for layer", + "name-data": "Data", + "name-display-tooltip": "Display tooltip", + "name-layer-type": "Layer type", + "name-opacity": "Opacity" + }, "layers-editor": { "label-add-layer": "Add layer", "no-layers": "No layers?" @@ -7200,16 +7267,35 @@ "label-zoom": "Zoom", "use-current-map-settings": "Use current map settings" }, + "markers-layer": { + "description-show-legend": "Show map legend", + "name-show-legend": "Show legend", + "name-styles": "Styles" + }, "markers-legend": { "title-symbol": "Symbol" }, "measure-overlay": { "tooltip-show-measure-tools": "Show measure tools" }, + "name-initial-view": "Initial view", + "name-mouse-wheel-zoom": "Mouse wheel zoom", + "name-share-view": "Share view", + "name-show-attribution": "Show attribution", + "name-show-debug": "Show debug", + "name-show-measure": "Show measure tools", + "name-show-scale": "Show scale", + "name-show-zoom": "Show zoom control", + "name-tooltip": "Tooltip", "plugin": { "basemap-layer-configured-server-admin": "The basemap layer is configured by the server admin." }, "style-editor": { + "horizontal-align-options": { + "label-center": "Center", + "label-left": "Left", + "label-right": "Right" + }, "label-align": "Align", "label-baseline": "Baseline", "label-color": "Color", @@ -7223,7 +7309,12 @@ "label-symbol-vertical-align": "Symbol vertical align", "label-text-label": "Text label", "label-x-offset": "X offset", - "label-y-offset": "Y offset" + "label-y-offset": "Y offset", + "vertical-align-options": { + "label-bottom": "Bottom", + "label-center": "Center", + "label-top": "Top" + } }, "style-rule-editor": { "aria-label-comparison-operator": "Comparison operator", @@ -7234,6 +7325,15 @@ "placeholder-feature-property": "Feature property", "placeholder-numeric-value": "Numeric value", "placeholder-value": "value" + }, + "tooltip-options": { + "description-details": "Show popup on hover", + "description-none": "Show contents on click, not hover", + "label-details": "Details", + "label-none": "None" + }, + "utils": { + "get-next-layer-name": "Layer {{name}}" } }, "get-enterprise": {