@yuneta/gobj-ui 7.23.110 → 7.23.112

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -942,7 +942,7 @@ function mt_create$21(gobj) {
942
942
  /***************************************************************
943
943
  * Framework Method: Start
944
944
  ***************************************************************/
945
- function mt_start$18(gobj) {
945
+ function mt_start$19(gobj) {
946
946
  let config = (0, _yuneta_gobj_js.gobj_read_attr)(gobj, "config") || {};
947
947
  let priv = gobj.priv;
948
948
  if (!validate_config(config)) {
@@ -1011,7 +1011,7 @@ function mt_start$18(gobj) {
1011
1011
  /***************************************************************
1012
1012
  * Framework Method: Stop
1013
1013
  ***************************************************************/
1014
- function mt_stop$18(gobj) {
1014
+ function mt_stop$19(gobj) {
1015
1015
  let priv = gobj.priv;
1016
1016
  if (!priv) return 0;
1017
1017
  close_toolbar_dropdown(gobj);
@@ -2556,8 +2556,8 @@ function ac_nav_item_close(gobj, event, kw, src) {
2556
2556
  ***************************************************************/
2557
2557
  var gmt$21 = {
2558
2558
  mt_create: mt_create$21,
2559
- mt_start: mt_start$18,
2560
- mt_stop: mt_stop$18,
2559
+ mt_start: mt_start$19,
2560
+ mt_stop: mt_stop$19,
2561
2561
  mt_destroy: mt_destroy$21
2562
2562
  };
2563
2563
  function create_gclass$21(gclass_name) {
@@ -4897,11 +4897,11 @@ function mt_create$18(gobj) {
4897
4897
  /***************************************************************
4898
4898
  * Framework Method: Start
4899
4899
  ***************************************************************/
4900
- function mt_start$17(gobj) {}
4900
+ function mt_start$18(gobj) {}
4901
4901
  /***************************************************************
4902
4902
  * Framework Method: Stop
4903
4903
  ***************************************************************/
4904
- function mt_stop$17(gobj) {
4904
+ function mt_stop$18(gobj) {
4905
4905
  (0, _yuneta_gobj_js.gobj_stop_children)(gobj);
4906
4906
  }
4907
4907
  /***************************************************************
@@ -5188,8 +5188,8 @@ function ac_resize$5(gobj, event, kw, src) {
5188
5188
  ***************************/
5189
5189
  var gmt$18 = {
5190
5190
  mt_create: mt_create$18,
5191
- mt_start: mt_start$17,
5192
- mt_stop: mt_stop$17,
5191
+ mt_start: mt_start$18,
5192
+ mt_stop: mt_stop$18,
5193
5193
  mt_destroy: mt_destroy$18
5194
5194
  };
5195
5195
  /***************************************************************
@@ -5431,11 +5431,11 @@ function mt_create$17(gobj) {
5431
5431
  /***************************************************************
5432
5432
  * Framework Method: Start
5433
5433
  ***************************************************************/
5434
- function mt_start$16(gobj) {}
5434
+ function mt_start$17(gobj) {}
5435
5435
  /***************************************************************
5436
5436
  * Framework Method: Stop
5437
5437
  ***************************************************************/
5438
- function mt_stop$16(gobj) {
5438
+ function mt_stop$17(gobj) {
5439
5439
  (0, _yuneta_gobj_js.gobj_stop_children)(gobj);
5440
5440
  }
5441
5441
  /***************************************************************
@@ -5795,8 +5795,8 @@ function ac_resize$4(gobj, event, kw, src) {
5795
5795
  ***************************/
5796
5796
  var gmt$17 = {
5797
5797
  mt_create: mt_create$17,
5798
- mt_start: mt_start$16,
5799
- mt_stop: mt_stop$16,
5798
+ mt_start: mt_start$17,
5799
+ mt_stop: mt_stop$17,
5800
5800
  mt_destroy: mt_destroy$17
5801
5801
  };
5802
5802
  /***************************************************************
@@ -6922,14 +6922,14 @@ function mt_destroy$16(gobj) {
6922
6922
  /************************************************************
6923
6923
  * Framework Method start
6924
6924
  ************************************************************/
6925
- function mt_start$15(gobj) {
6925
+ function mt_start$16(gobj) {
6926
6926
  let record = (0, _yuneta_gobj_js.gobj_read_attr)(gobj, "record");
6927
6927
  if (record) (0, _yuneta_gobj_js.gobj_send_event)(gobj, "EV_LOAD_RECORD", record, gobj);
6928
6928
  }
6929
6929
  /************************************************************
6930
6930
  * Framework Method stop
6931
6931
  ************************************************************/
6932
- function mt_stop$15(gobj) {}
6932
+ function mt_stop$16(gobj) {}
6933
6933
  /***************************
6934
6934
  * Local Methods
6935
6935
  ***************************/
@@ -7012,8 +7012,10 @@ function toolbar_button$1(gobj, name) {
7012
7012
  "button",
7013
7013
  {
7014
7014
  class: "button p-1 button-save",
7015
- title: "save",
7016
- "aria-label": "save",
7015
+ title: (0, i18next.t)("save"),
7016
+ "data-i18n-title": "save",
7017
+ "aria-label": (0, i18next.t)("save"),
7018
+ "data-i18n-aria-label": "save",
7017
7019
  disabled: true
7018
7020
  },
7019
7021
  [[
@@ -7037,8 +7039,10 @@ function toolbar_button$1(gobj, name) {
7037
7039
  "button",
7038
7040
  {
7039
7041
  class: "button p-1 button-undo",
7040
- title: "undo",
7041
- "aria-label": "undo",
7042
+ title: (0, i18next.t)("undo"),
7043
+ "data-i18n-title": "undo",
7044
+ "aria-label": (0, i18next.t)("undo"),
7045
+ "data-i18n-aria-label": "undo",
7042
7046
  disabled: true
7043
7047
  },
7044
7048
  [[
@@ -7062,8 +7066,10 @@ function toolbar_button$1(gobj, name) {
7062
7066
  "button",
7063
7067
  {
7064
7068
  class: "button p-1 button-clear",
7065
- title: "clear",
7066
- "aria-label": "clear"
7069
+ title: (0, i18next.t)("clear"),
7070
+ "data-i18n-title": "clear",
7071
+ "aria-label": (0, i18next.t)("clear"),
7072
+ "data-i18n-aria-label": "clear"
7067
7073
  },
7068
7074
  [[
7069
7075
  "span",
@@ -7086,8 +7092,10 @@ function toolbar_button$1(gobj, name) {
7086
7092
  "button",
7087
7093
  {
7088
7094
  class: "button p-1 button-copy",
7089
- title: "copy",
7090
- "aria-label": "copy"
7095
+ title: (0, i18next.t)("copy"),
7096
+ "data-i18n-title": "copy",
7097
+ "aria-label": (0, i18next.t)("copy"),
7098
+ "data-i18n-aria-label": "copy"
7091
7099
  },
7092
7100
  [[
7093
7101
  "span",
@@ -7110,8 +7118,10 @@ function toolbar_button$1(gobj, name) {
7110
7118
  "button",
7111
7119
  {
7112
7120
  class: "button p-1 button-paste",
7113
- title: "paste",
7114
- "aria-label": "paste"
7121
+ title: (0, i18next.t)("paste"),
7122
+ "data-i18n-title": "paste",
7123
+ "aria-label": (0, i18next.t)("paste"),
7124
+ "data-i18n-aria-label": "paste"
7115
7125
  },
7116
7126
  [[
7117
7127
  "span",
@@ -8372,7 +8382,7 @@ function template2columns(gobj, columns, template, sub_elements) {
8372
8382
  column.editorParams = {
8373
8383
  format: "dd/MM/yyyy hh:mm",
8374
8384
  verticalNavigation: "table",
8375
- elementAttributes: { title: "slide bar to choose option" }
8385
+ elementAttributes: { title: (0, i18next.t)("slide bar to choose option") }
8376
8386
  };
8377
8387
  field_desc.real_type;
8378
8388
  break;
@@ -9154,8 +9164,8 @@ function cmd_get_picked_files(gobj, cmd, kw, src) {
9154
9164
  }
9155
9165
  var gmt$16 = {
9156
9166
  mt_create: mt_create$16,
9157
- mt_start: mt_start$15,
9158
- mt_stop: mt_stop$15,
9167
+ mt_start: mt_start$16,
9168
+ mt_stop: mt_stop$16,
9159
9169
  mt_destroy: mt_destroy$16,
9160
9170
  mt_command_parser: mt_command_parser$2
9161
9171
  };
@@ -9314,7 +9324,9 @@ var EditControl = class {
9314
9324
  {
9315
9325
  class: "button is-small is-flex is-align-items-center is-justify-content-center",
9316
9326
  title: (0, i18next.t)("maplibre.drag_mark"),
9317
- "aria-label": (0, i18next.t)("maplibre.drag_mark")
9327
+ "data-i18n-title": "maplibre.drag_mark",
9328
+ "aria-label": (0, i18next.t)("maplibre.drag_mark"),
9329
+ "data-i18n-aria-label": "maplibre.drag_mark"
9318
9330
  },
9319
9331
  (0, _yuneta_gobj_js.parseSVG)(`
9320
9332
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="22" height="22" fill="#CCCCCC"><path d="M273 7c-9.4-9.4-24.6-9.4-33.9 0L167 79c-9.4 9.4-9.4 24.6 0 33.9s24.6 9.4 33.9 0l31-31L232 232 81.9 232l31-31c9.4-9.4 9.4-24.6 0-33.9s-24.6-9.4-33.9 0L7 239c-9.4 9.4-9.4 24.6 0 33.9l72 72c9.4 9.4 24.6 9.4 33.9 0s9.4-24.6 0-33.9l-31-31L232 280l0 150.1-31-31c-9.4-9.4-24.6-9.4-33.9 0s-9.4 24.6 0 33.9l72 72c9.4 9.4 24.6 9.4 33.9 0l72-72c9.4-9.4 9.4-24.6 0-33.9s-24.6-9.4-33.9 0l-31 31L280 280l150.1 0-31 31c-9.4 9.4-9.4 24.6 0 33.9s24.6 9.4 33.9 0l72-72c9.4-9.4 9.4-24.6 0-33.9l-72-72c-9.4-9.4-24.6-9.4-33.9 0s-9.4 24.6 0 33.9l31 31L280 232l0-150.1 31 31c9.4 9.4 24.6 9.4 33.9 0s9.4-24.6 0-33.9L273 7z"/></svg>
@@ -9373,7 +9385,9 @@ var MarkerControl = class {
9373
9385
  {
9374
9386
  class: "button is-small is-flex is-align-items-center is-justify-content-center",
9375
9387
  title: (0, i18next.t)("maplibre.center_map"),
9376
- "aria-label": (0, i18next.t)("maplibre.center_map")
9388
+ "data-i18n-title": "maplibre.center_map",
9389
+ "aria-label": (0, i18next.t)("maplibre.center_map"),
9390
+ "data-i18n-aria-label": "maplibre.center_map"
9377
9391
  },
9378
9392
  (0, _yuneta_gobj_js.parseSVG)(`
9379
9393
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512" width="22" height="22"><path d="M15 15C24.4 5.7 39.6 5.7 49 15l63 63L112 40c0-13.3 10.7-24 24-24s24 10.7 24 24l0 96c0 13.3-10.7 24-24 24l-96 0c-13.3 0-24-10.7-24-24s10.7-24 24-24l38.1 0L15 49C5.7 39.6 5.7 24.4 15 15zM133.5 243.9C158.6 193.6 222.7 112 320 112s161.4 81.6 186.5 131.9c3.8 7.6 3.8 16.5 0 24.2C481.4 318.4 417.3 400 320 400s-161.4-81.6-186.5-131.9c-3.8-7.6-3.8-16.5 0-24.2zM320 320a64 64 0 1 0 0-128 64 64 0 1 0 0 128zM591 15c9.4-9.4 24.6-9.4 33.9 0s9.4 24.6 0 33.9l-63 63 38.1 0c13.3 0 24 10.7 24 24s-10.7 24-24 24l-96 0c-13.3 0-24-10.7-24-24l0-96c0-13.3 10.7-24 24-24s24 10.7 24 24l0 38.1 63-63zM15 497c-9.4-9.4-9.4-24.6 0-33.9l63-63L40 400c-13.3 0-24-10.7-24-24s10.7-24 24-24l96 0c13.3 0 24 10.7 24 24l0 96c0 13.3-10.7 24-24 24s-24-10.7-24-24l0-38.1L49 497c-9.4 9.4-24.6 9.4-33.9 0zm576 0l-63-63 0 38.1c0 13.3-10.7 24-24 24s-24-10.7-24-24l0-96c0-13.3 10.7-24 24-24l96 0c13.3 0 24 10.7 24 24s-10.7 24-24 24l-38.1 0 63 63c9.4 9.4 9.4 24.6 0 33.9s-24.6 9.4-33.9 0z"/></svg>
@@ -9390,7 +9404,9 @@ var MarkerControl = class {
9390
9404
  {
9391
9405
  class: "button is-small is-flex is-align-items-center is-justify-content-center",
9392
9406
  title: (0, i18next.t)("maplibre.user_location"),
9393
- "aria-label": (0, i18next.t)("maplibre.user_location")
9407
+ "data-i18n-title": "maplibre.user_location",
9408
+ "aria-label": (0, i18next.t)("maplibre.user_location"),
9409
+ "data-i18n-aria-label": "maplibre.user_location"
9394
9410
  },
9395
9411
  (0, _yuneta_gobj_js.parseSVG)(`
9396
9412
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="22" height="22" fill="#CCCCCC"><path d="M256 0c17.7 0 32 14.3 32 32l0 34.7C368.4 80.1 431.9 143.6 445.3 224l34.7 0c17.7 0 32 14.3 32 32s-14.3 32-32 32l-34.7 0C431.9 368.4 368.4 431.9 288 445.3l0 34.7c0 17.7-14.3 32-32 32s-32-14.3-32-32l0-34.7C143.6 431.9 80.1 368.4 66.7 288L32 288c-17.7 0-32-14.3-32-32s14.3-32 32-32l34.7 0C80.1 143.6 143.6 80.1 224 66.7L224 32c0-17.7 14.3-32 32-32zM128 256a128 128 0 1 0 256 0 128 128 0 1 0 -256 0zm128-80a80 80 0 1 1 0 160 80 80 0 1 1 0-160z"/></svg>
@@ -9417,6 +9433,78 @@ var MarkerControl = class {
9417
9433
  (0, _yuneta_gobj_js.gobj_send_event)(this.gobj, "EV_CONTROL_MAP", { user_location: this._enable_user_location }, this.gobj);
9418
9434
  }
9419
9435
  };
9436
+ /***********************************************************************
9437
+ * MAPLIBRE'S OWN CHROME, IN THE APP'S LANGUAGE
9438
+ *
9439
+ * Everything maplibre draws with words -- the zoom tooltips, the
9440
+ * geolocate button, the attribution toggle, a popup's close, and the
9441
+ * notice that teaches the Ctrl + wheel gesture -- comes from its
9442
+ * `locale`, an option merged over its own English defaults at
9443
+ * construction. So a map in a Spanish app was saying *"Zoom in"* and
9444
+ * *"Use Ctrl + scroll to zoom the map"*, which is the same rule this
9445
+ * GUI applies to every other string.
9446
+ *
9447
+ * Two halves, because maplibre reads its strings ONCE, when each
9448
+ * control builds its DOM:
9449
+ *
9450
+ * `yui_maplibre_locale(t)` the `locale` option, for the map's
9451
+ * first paint;
9452
+ * `yui_maplibre_relocalize()` after a language change, which is
9453
+ * the half a `locale` alone cannot
9454
+ * do -- it writes the strings into
9455
+ * the DOM already drawn, and updates
9456
+ * the map's locale so anything built
9457
+ * later is right too.
9458
+ *
9459
+ * The scale units (`km`, `mi`, `nm`) are symbols and are left alone;
9460
+ * the MapLibre logo keeps its name, which is a brand.
9461
+ ***********************************************************************/
9462
+ function yui_maplibre_locale(t) {
9463
+ return {
9464
+ "NavigationControl.ZoomIn": t("zoom in"),
9465
+ "NavigationControl.ZoomOut": t("zoom out"),
9466
+ "NavigationControl.ResetBearing": t("drag to rotate the map, click to reset north"),
9467
+ "GeolocateControl.FindMyLocation": t("find my location"),
9468
+ "GeolocateControl.LocationNotAvailable": t("location not available"),
9469
+ "AttributionControl.ToggleAttribution": t("toggle attribution"),
9470
+ "AttributionControl.MapFeedback": t("map feedback"),
9471
+ "FullscreenControl.Enter": t("enter fullscreen"),
9472
+ "FullscreenControl.Exit": t("exit fullscreen"),
9473
+ "Popup.Close": t("close popup"),
9474
+ "Map.Title": t("map"),
9475
+ "Marker.Title": t("map marker"),
9476
+ "CooperativeGesturesHandler.WindowsHelpText": t("use ctrl + scroll to zoom the map"),
9477
+ "CooperativeGesturesHandler.MacHelpText": t("use cmd + scroll to zoom the map"),
9478
+ "CooperativeGesturesHandler.MobileHelpText": t("use two fingers to move the map")
9479
+ };
9480
+ }
9481
+ function label_ctrl($root, selector, text) {
9482
+ if (!$root || !text) return;
9483
+ for (const $el of $root.querySelectorAll(selector)) {
9484
+ $el.setAttribute("title", text);
9485
+ $el.setAttribute("aria-label", text);
9486
+ }
9487
+ }
9488
+ function yui_maplibre_relocalize(map, t) {
9489
+ if (!map || typeof map.getContainer !== "function") return;
9490
+ const strings = yui_maplibre_locale(t);
9491
+ try {
9492
+ map._locale = Object.assign({}, map._locale, strings);
9493
+ } catch (e) {}
9494
+ const $c = map.getContainer();
9495
+ label_ctrl($c, ".maplibregl-ctrl-zoom-in", strings["NavigationControl.ZoomIn"]);
9496
+ label_ctrl($c, ".maplibregl-ctrl-zoom-out", strings["NavigationControl.ZoomOut"]);
9497
+ label_ctrl($c, ".maplibregl-ctrl-compass", strings["NavigationControl.ResetBearing"]);
9498
+ label_ctrl($c, ".maplibregl-ctrl-geolocate", strings["GeolocateControl.FindMyLocation"]);
9499
+ label_ctrl($c, ".maplibregl-ctrl-attrib-button", strings["AttributionControl.ToggleAttribution"]);
9500
+ label_ctrl($c, ".maplibregl-ctrl-fullscreen", strings["FullscreenControl.Enter"]);
9501
+ label_ctrl($c, ".maplibregl-popup-close-button", strings["Popup.Close"]);
9502
+ const mac = typeof navigator !== "undefined" && (navigator.userAgent || "").includes("Mac");
9503
+ const $desktop = $c.querySelector(".maplibregl-desktop-message");
9504
+ if ($desktop) $desktop.textContent = mac ? strings["CooperativeGesturesHandler.MacHelpText"] : strings["CooperativeGesturesHandler.WindowsHelpText"];
9505
+ const $mobile = $c.querySelector(".maplibregl-mobile-message");
9506
+ if ($mobile) $mobile.textContent = strings["CooperativeGesturesHandler.MobileHelpText"];
9507
+ }
9420
9508
  //#endregion
9421
9509
  //#region src/c_yui_map.js
9422
9510
  /***********************************************************************
@@ -9431,6 +9519,7 @@ var MarkerControl = class {
9431
9519
  * Constants
9432
9520
  ***************************************************************/
9433
9521
  var GCLASS_NAME$15 = "C_YUI_MAP";
9522
+ var GESTURE_HINT_MS = 2e3;
9434
9523
  /***************************************************************
9435
9524
  * Data
9436
9525
  ***************************************************************/
@@ -9457,6 +9546,7 @@ var attrs_table$15 = [
9457
9546
  ];
9458
9547
  var PRIVATE_DATA$15 = {
9459
9548
  xmap: null,
9549
+ gesture_hint_timer: null,
9460
9550
  geojson: null,
9461
9551
  resizeObserver: null,
9462
9552
  width: 0,
@@ -9481,7 +9571,8 @@ function mt_create$15(gobj) {
9481
9571
  if ($map) $map.classList.add(GCLASS_NAME$15);
9482
9572
  Object.assign(map_settings, {
9483
9573
  container: $map,
9484
- cooperativeGestures: true
9574
+ cooperativeGestures: true,
9575
+ locale: yui_maplibre_locale(i18next.t)
9485
9576
  });
9486
9577
  priv.onClick = (ev) => {
9487
9578
  onClick(gobj, ev);
@@ -9499,6 +9590,16 @@ function mt_create$15(gobj) {
9499
9590
  xtouchStart(gobj, ev);
9500
9591
  };
9501
9592
  const map = priv.xmap = new maplibre_gl.Map(map_settings);
9593
+ map.on("cooperativegestureprevented", () => {
9594
+ const $s = map.getCanvasContainer().querySelector(".maplibregl-cooperative-gesture-screen");
9595
+ if (!$s) return;
9596
+ $s.classList.add("MAP_GESTURE_SHOWN");
9597
+ if (priv.gesture_hint_timer) clearTimeout(priv.gesture_hint_timer);
9598
+ priv.gesture_hint_timer = setTimeout(() => {
9599
+ priv.gesture_hint_timer = null;
9600
+ $s.classList.remove("MAP_GESTURE_SHOWN");
9601
+ }, GESTURE_HINT_MS);
9602
+ });
9502
9603
  map.addControl(new maplibre_gl.NavigationControl());
9503
9604
  map.addControl(new MarkerControl(gobj, {}), "top-right");
9504
9605
  map.addControl(new EditControl(gobj, { showMarkerDrag: true }), "top-right");
@@ -9528,10 +9629,46 @@ function mt_create$15(gobj) {
9528
9629
  }
9529
9630
  }
9530
9631
  /***************************************************************
9632
+ * The application changed language: maplibre's own words are
9633
+ * rewritten in place, and the map's locale with them so a
9634
+ * control or a popup built later is right too.
9635
+ ***************************************************************/
9636
+ function ac_language_changed$9(gobj, event, kw, src) {
9637
+ let priv = gobj.priv;
9638
+ if (priv.xmap) yui_maplibre_relocalize(priv.xmap, i18next.t);
9639
+ return 0;
9640
+ }
9641
+ /***************************************************************
9642
+ * Framework Method: Start
9643
+ *
9644
+ * The application's LANGUAGE: what maplibre draws with words is
9645
+ * built from its `locale` when each control builds its DOM, so
9646
+ * `refresh_language()` -- which reaches what carries an i18n key
9647
+ * in OUR dom -- cannot touch any of it. The shell says when the
9648
+ * language changed and this view rewrites those strings.
9649
+ ***************************************************************/
9650
+ function mt_start$15(gobj) {
9651
+ let shell = yui_shell_of(gobj);
9652
+ if (shell) (0, _yuneta_gobj_js.gobj_subscribe_event)(shell, "EV_LANGUAGE_CHANGED", {}, gobj);
9653
+ return 0;
9654
+ }
9655
+ /***************************************************************
9656
+ * Framework Method: Stop
9657
+ ***************************************************************/
9658
+ function mt_stop$15(gobj) {
9659
+ let shell = yui_shell_of(gobj);
9660
+ if (shell) (0, _yuneta_gobj_js.gobj_unsubscribe_event)(shell, "EV_LANGUAGE_CHANGED", {}, gobj);
9661
+ return 0;
9662
+ }
9663
+ /***************************************************************
9531
9664
  * Framework Method: Destroy
9532
9665
  ***************************************************************/
9533
9666
  function mt_destroy$15(gobj) {
9534
9667
  let priv = gobj.priv;
9668
+ if (priv.gesture_hint_timer) {
9669
+ clearTimeout(priv.gesture_hint_timer);
9670
+ priv.gesture_hint_timer = null;
9671
+ }
9535
9672
  if (priv.resizeObserver) {
9536
9673
  priv.resizeObserver.disconnect();
9537
9674
  priv.resizeObserver = null;
@@ -9992,6 +10129,8 @@ function ac_hide$10(gobj, event, kw, src) {
9992
10129
  ***************************/
9993
10130
  var gmt$15 = {
9994
10131
  mt_create: mt_create$15,
10132
+ mt_start: mt_start$15,
10133
+ mt_stop: mt_stop$15,
9995
10134
  mt_destroy: mt_destroy$15
9996
10135
  };
9997
10136
  /***************************************************************
@@ -10003,6 +10142,7 @@ function create_gclass$15(gclass_name) {
10003
10142
  return -1;
10004
10143
  }
10005
10144
  __gclass__$15 = (0, _yuneta_gobj_js.gclass_create)(gclass_name, [
10145
+ ["EV_LANGUAGE_CHANGED", 0],
10006
10146
  ["EV_EDIT_MAP", 0],
10007
10147
  ["EV_CONTROL_MAP", 0],
10008
10148
  ["EV_MAP_ON_LOAD", 0],
@@ -10011,6 +10151,11 @@ function create_gclass$15(gclass_name) {
10011
10151
  ["EV_SHOW", 0],
10012
10152
  ["EV_HIDE", 0]
10013
10153
  ], [["ST_IDLE", [
10154
+ [
10155
+ "EV_LANGUAGE_CHANGED",
10156
+ ac_language_changed$9,
10157
+ null
10158
+ ],
10014
10159
  [
10015
10160
  "EV_EDIT_MAP",
10016
10161
  ac_edit_map,
@@ -20409,8 +20554,10 @@ function render_tabs(gobj, items) {
20409
20554
  class: "icon is-small yui-nav-close ml-2",
20410
20555
  "data-close-item": it.id,
20411
20556
  role: "button",
20412
- "aria-label": "close",
20413
- title: "close"
20557
+ "aria-label": (0, i18next.t)("close"),
20558
+ "data-i18n-aria-label": "close",
20559
+ title: (0, i18next.t)("close"),
20560
+ "data-i18n-title": "close"
20414
20561
  },
20415
20562
  ["i", {
20416
20563
  class: "yi-xmark",
@@ -24858,7 +25005,8 @@ function create_tabulator(gobj) {
24858
25005
  }
24859
25006
  if (write_plan(gobj).in_row_icons) columns.push({
24860
25007
  field: "_operation",
24861
- title: "Op",
25008
+ title: "",
25009
+ titleFormatter: () => (0, i18next.t)("operations"),
24862
25010
  hozAlign: "center",
24863
25011
  frozen: "right",
24864
25012
  visible: false,
@@ -937,7 +937,7 @@ function mt_create$21(gobj) {
937
937
  /***************************************************************
938
938
  * Framework Method: Start
939
939
  ***************************************************************/
940
- function mt_start$18(gobj) {
940
+ function mt_start$19(gobj) {
941
941
  let config = gobj_read_attr(gobj, "config") || {};
942
942
  let priv = gobj.priv;
943
943
  if (!validate_config(config)) {
@@ -1006,7 +1006,7 @@ function mt_start$18(gobj) {
1006
1006
  /***************************************************************
1007
1007
  * Framework Method: Stop
1008
1008
  ***************************************************************/
1009
- function mt_stop$18(gobj) {
1009
+ function mt_stop$19(gobj) {
1010
1010
  let priv = gobj.priv;
1011
1011
  if (!priv) return 0;
1012
1012
  close_toolbar_dropdown(gobj);
@@ -2551,8 +2551,8 @@ function ac_nav_item_close(gobj, event, kw, src) {
2551
2551
  ***************************************************************/
2552
2552
  var gmt$21 = {
2553
2553
  mt_create: mt_create$21,
2554
- mt_start: mt_start$18,
2555
- mt_stop: mt_stop$18,
2554
+ mt_start: mt_start$19,
2555
+ mt_stop: mt_stop$19,
2556
2556
  mt_destroy: mt_destroy$21
2557
2557
  };
2558
2558
  function create_gclass$21(gclass_name) {
@@ -4892,11 +4892,11 @@ function mt_create$18(gobj) {
4892
4892
  /***************************************************************
4893
4893
  * Framework Method: Start
4894
4894
  ***************************************************************/
4895
- function mt_start$17(gobj) {}
4895
+ function mt_start$18(gobj) {}
4896
4896
  /***************************************************************
4897
4897
  * Framework Method: Stop
4898
4898
  ***************************************************************/
4899
- function mt_stop$17(gobj) {
4899
+ function mt_stop$18(gobj) {
4900
4900
  gobj_stop_children(gobj);
4901
4901
  }
4902
4902
  /***************************************************************
@@ -5183,8 +5183,8 @@ function ac_resize$5(gobj, event, kw, src) {
5183
5183
  ***************************/
5184
5184
  var gmt$18 = {
5185
5185
  mt_create: mt_create$18,
5186
- mt_start: mt_start$17,
5187
- mt_stop: mt_stop$17,
5186
+ mt_start: mt_start$18,
5187
+ mt_stop: mt_stop$18,
5188
5188
  mt_destroy: mt_destroy$18
5189
5189
  };
5190
5190
  /***************************************************************
@@ -5426,11 +5426,11 @@ function mt_create$17(gobj) {
5426
5426
  /***************************************************************
5427
5427
  * Framework Method: Start
5428
5428
  ***************************************************************/
5429
- function mt_start$16(gobj) {}
5429
+ function mt_start$17(gobj) {}
5430
5430
  /***************************************************************
5431
5431
  * Framework Method: Stop
5432
5432
  ***************************************************************/
5433
- function mt_stop$16(gobj) {
5433
+ function mt_stop$17(gobj) {
5434
5434
  gobj_stop_children(gobj);
5435
5435
  }
5436
5436
  /***************************************************************
@@ -5790,8 +5790,8 @@ function ac_resize$4(gobj, event, kw, src) {
5790
5790
  ***************************/
5791
5791
  var gmt$17 = {
5792
5792
  mt_create: mt_create$17,
5793
- mt_start: mt_start$16,
5794
- mt_stop: mt_stop$16,
5793
+ mt_start: mt_start$17,
5794
+ mt_stop: mt_stop$17,
5795
5795
  mt_destroy: mt_destroy$17
5796
5796
  };
5797
5797
  /***************************************************************
@@ -6917,14 +6917,14 @@ function mt_destroy$16(gobj) {
6917
6917
  /************************************************************
6918
6918
  * Framework Method start
6919
6919
  ************************************************************/
6920
- function mt_start$15(gobj) {
6920
+ function mt_start$16(gobj) {
6921
6921
  let record = gobj_read_attr(gobj, "record");
6922
6922
  if (record) gobj_send_event(gobj, "EV_LOAD_RECORD", record, gobj);
6923
6923
  }
6924
6924
  /************************************************************
6925
6925
  * Framework Method stop
6926
6926
  ************************************************************/
6927
- function mt_stop$15(gobj) {}
6927
+ function mt_stop$16(gobj) {}
6928
6928
  /***************************
6929
6929
  * Local Methods
6930
6930
  ***************************/
@@ -7007,8 +7007,10 @@ function toolbar_button$1(gobj, name) {
7007
7007
  "button",
7008
7008
  {
7009
7009
  class: "button p-1 button-save",
7010
- title: "save",
7011
- "aria-label": "save",
7010
+ title: t("save"),
7011
+ "data-i18n-title": "save",
7012
+ "aria-label": t("save"),
7013
+ "data-i18n-aria-label": "save",
7012
7014
  disabled: true
7013
7015
  },
7014
7016
  [[
@@ -7032,8 +7034,10 @@ function toolbar_button$1(gobj, name) {
7032
7034
  "button",
7033
7035
  {
7034
7036
  class: "button p-1 button-undo",
7035
- title: "undo",
7036
- "aria-label": "undo",
7037
+ title: t("undo"),
7038
+ "data-i18n-title": "undo",
7039
+ "aria-label": t("undo"),
7040
+ "data-i18n-aria-label": "undo",
7037
7041
  disabled: true
7038
7042
  },
7039
7043
  [[
@@ -7057,8 +7061,10 @@ function toolbar_button$1(gobj, name) {
7057
7061
  "button",
7058
7062
  {
7059
7063
  class: "button p-1 button-clear",
7060
- title: "clear",
7061
- "aria-label": "clear"
7064
+ title: t("clear"),
7065
+ "data-i18n-title": "clear",
7066
+ "aria-label": t("clear"),
7067
+ "data-i18n-aria-label": "clear"
7062
7068
  },
7063
7069
  [[
7064
7070
  "span",
@@ -7081,8 +7087,10 @@ function toolbar_button$1(gobj, name) {
7081
7087
  "button",
7082
7088
  {
7083
7089
  class: "button p-1 button-copy",
7084
- title: "copy",
7085
- "aria-label": "copy"
7090
+ title: t("copy"),
7091
+ "data-i18n-title": "copy",
7092
+ "aria-label": t("copy"),
7093
+ "data-i18n-aria-label": "copy"
7086
7094
  },
7087
7095
  [[
7088
7096
  "span",
@@ -7105,8 +7113,10 @@ function toolbar_button$1(gobj, name) {
7105
7113
  "button",
7106
7114
  {
7107
7115
  class: "button p-1 button-paste",
7108
- title: "paste",
7109
- "aria-label": "paste"
7116
+ title: t("paste"),
7117
+ "data-i18n-title": "paste",
7118
+ "aria-label": t("paste"),
7119
+ "data-i18n-aria-label": "paste"
7110
7120
  },
7111
7121
  [[
7112
7122
  "span",
@@ -8367,7 +8377,7 @@ function template2columns(gobj, columns, template, sub_elements) {
8367
8377
  column.editorParams = {
8368
8378
  format: "dd/MM/yyyy hh:mm",
8369
8379
  verticalNavigation: "table",
8370
- elementAttributes: { title: "slide bar to choose option" }
8380
+ elementAttributes: { title: t("slide bar to choose option") }
8371
8381
  };
8372
8382
  field_desc.real_type;
8373
8383
  break;
@@ -9149,8 +9159,8 @@ function cmd_get_picked_files(gobj, cmd, kw, src) {
9149
9159
  }
9150
9160
  var gmt$16 = {
9151
9161
  mt_create: mt_create$16,
9152
- mt_start: mt_start$15,
9153
- mt_stop: mt_stop$15,
9162
+ mt_start: mt_start$16,
9163
+ mt_stop: mt_stop$16,
9154
9164
  mt_destroy: mt_destroy$16,
9155
9165
  mt_command_parser: mt_command_parser$2
9156
9166
  };
@@ -9309,7 +9319,9 @@ var EditControl = class {
9309
9319
  {
9310
9320
  class: "button is-small is-flex is-align-items-center is-justify-content-center",
9311
9321
  title: t("maplibre.drag_mark"),
9312
- "aria-label": t("maplibre.drag_mark")
9322
+ "data-i18n-title": "maplibre.drag_mark",
9323
+ "aria-label": t("maplibre.drag_mark"),
9324
+ "data-i18n-aria-label": "maplibre.drag_mark"
9313
9325
  },
9314
9326
  parseSVG(`
9315
9327
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="22" height="22" fill="#CCCCCC"><path d="M273 7c-9.4-9.4-24.6-9.4-33.9 0L167 79c-9.4 9.4-9.4 24.6 0 33.9s24.6 9.4 33.9 0l31-31L232 232 81.9 232l31-31c9.4-9.4 9.4-24.6 0-33.9s-24.6-9.4-33.9 0L7 239c-9.4 9.4-9.4 24.6 0 33.9l72 72c9.4 9.4 24.6 9.4 33.9 0s9.4-24.6 0-33.9l-31-31L232 280l0 150.1-31-31c-9.4-9.4-24.6-9.4-33.9 0s-9.4 24.6 0 33.9l72 72c9.4 9.4 24.6 9.4 33.9 0l72-72c9.4-9.4 9.4-24.6 0-33.9s-24.6-9.4-33.9 0l-31 31L280 280l150.1 0-31 31c-9.4 9.4-9.4 24.6 0 33.9s24.6 9.4 33.9 0l72-72c9.4-9.4 9.4-24.6 0-33.9l-72-72c-9.4-9.4-24.6-9.4-33.9 0s-9.4 24.6 0 33.9l31 31L280 232l0-150.1 31 31c9.4 9.4 24.6 9.4 33.9 0s9.4-24.6 0-33.9L273 7z"/></svg>
@@ -9368,7 +9380,9 @@ var MarkerControl = class {
9368
9380
  {
9369
9381
  class: "button is-small is-flex is-align-items-center is-justify-content-center",
9370
9382
  title: t("maplibre.center_map"),
9371
- "aria-label": t("maplibre.center_map")
9383
+ "data-i18n-title": "maplibre.center_map",
9384
+ "aria-label": t("maplibre.center_map"),
9385
+ "data-i18n-aria-label": "maplibre.center_map"
9372
9386
  },
9373
9387
  parseSVG(`
9374
9388
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512" width="22" height="22"><path d="M15 15C24.4 5.7 39.6 5.7 49 15l63 63L112 40c0-13.3 10.7-24 24-24s24 10.7 24 24l0 96c0 13.3-10.7 24-24 24l-96 0c-13.3 0-24-10.7-24-24s10.7-24 24-24l38.1 0L15 49C5.7 39.6 5.7 24.4 15 15zM133.5 243.9C158.6 193.6 222.7 112 320 112s161.4 81.6 186.5 131.9c3.8 7.6 3.8 16.5 0 24.2C481.4 318.4 417.3 400 320 400s-161.4-81.6-186.5-131.9c-3.8-7.6-3.8-16.5 0-24.2zM320 320a64 64 0 1 0 0-128 64 64 0 1 0 0 128zM591 15c9.4-9.4 24.6-9.4 33.9 0s9.4 24.6 0 33.9l-63 63 38.1 0c13.3 0 24 10.7 24 24s-10.7 24-24 24l-96 0c-13.3 0-24-10.7-24-24l0-96c0-13.3 10.7-24 24-24s24 10.7 24 24l0 38.1 63-63zM15 497c-9.4-9.4-9.4-24.6 0-33.9l63-63L40 400c-13.3 0-24-10.7-24-24s10.7-24 24-24l96 0c13.3 0 24 10.7 24 24l0 96c0 13.3-10.7 24-24 24s-24-10.7-24-24l0-38.1L49 497c-9.4 9.4-24.6 9.4-33.9 0zm576 0l-63-63 0 38.1c0 13.3-10.7 24-24 24s-24-10.7-24-24l0-96c0-13.3 10.7-24 24-24l96 0c13.3 0 24 10.7 24 24s-10.7 24-24 24l-38.1 0 63 63c9.4 9.4 9.4 24.6 0 33.9s-24.6 9.4-33.9 0z"/></svg>
@@ -9385,7 +9399,9 @@ var MarkerControl = class {
9385
9399
  {
9386
9400
  class: "button is-small is-flex is-align-items-center is-justify-content-center",
9387
9401
  title: t("maplibre.user_location"),
9388
- "aria-label": t("maplibre.user_location")
9402
+ "data-i18n-title": "maplibre.user_location",
9403
+ "aria-label": t("maplibre.user_location"),
9404
+ "data-i18n-aria-label": "maplibre.user_location"
9389
9405
  },
9390
9406
  parseSVG(`
9391
9407
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="22" height="22" fill="#CCCCCC"><path d="M256 0c17.7 0 32 14.3 32 32l0 34.7C368.4 80.1 431.9 143.6 445.3 224l34.7 0c17.7 0 32 14.3 32 32s-14.3 32-32 32l-34.7 0C431.9 368.4 368.4 431.9 288 445.3l0 34.7c0 17.7-14.3 32-32 32s-32-14.3-32-32l0-34.7C143.6 431.9 80.1 368.4 66.7 288L32 288c-17.7 0-32-14.3-32-32s14.3-32 32-32l34.7 0C80.1 143.6 143.6 80.1 224 66.7L224 32c0-17.7 14.3-32 32-32zM128 256a128 128 0 1 0 256 0 128 128 0 1 0 -256 0zm128-80a80 80 0 1 1 0 160 80 80 0 1 1 0-160z"/></svg>
@@ -9412,6 +9428,78 @@ var MarkerControl = class {
9412
9428
  gobj_send_event(this.gobj, "EV_CONTROL_MAP", { user_location: this._enable_user_location }, this.gobj);
9413
9429
  }
9414
9430
  };
9431
+ /***********************************************************************
9432
+ * MAPLIBRE'S OWN CHROME, IN THE APP'S LANGUAGE
9433
+ *
9434
+ * Everything maplibre draws with words -- the zoom tooltips, the
9435
+ * geolocate button, the attribution toggle, a popup's close, and the
9436
+ * notice that teaches the Ctrl + wheel gesture -- comes from its
9437
+ * `locale`, an option merged over its own English defaults at
9438
+ * construction. So a map in a Spanish app was saying *"Zoom in"* and
9439
+ * *"Use Ctrl + scroll to zoom the map"*, which is the same rule this
9440
+ * GUI applies to every other string.
9441
+ *
9442
+ * Two halves, because maplibre reads its strings ONCE, when each
9443
+ * control builds its DOM:
9444
+ *
9445
+ * `yui_maplibre_locale(t)` the `locale` option, for the map's
9446
+ * first paint;
9447
+ * `yui_maplibre_relocalize()` after a language change, which is
9448
+ * the half a `locale` alone cannot
9449
+ * do -- it writes the strings into
9450
+ * the DOM already drawn, and updates
9451
+ * the map's locale so anything built
9452
+ * later is right too.
9453
+ *
9454
+ * The scale units (`km`, `mi`, `nm`) are symbols and are left alone;
9455
+ * the MapLibre logo keeps its name, which is a brand.
9456
+ ***********************************************************************/
9457
+ function yui_maplibre_locale(t) {
9458
+ return {
9459
+ "NavigationControl.ZoomIn": t("zoom in"),
9460
+ "NavigationControl.ZoomOut": t("zoom out"),
9461
+ "NavigationControl.ResetBearing": t("drag to rotate the map, click to reset north"),
9462
+ "GeolocateControl.FindMyLocation": t("find my location"),
9463
+ "GeolocateControl.LocationNotAvailable": t("location not available"),
9464
+ "AttributionControl.ToggleAttribution": t("toggle attribution"),
9465
+ "AttributionControl.MapFeedback": t("map feedback"),
9466
+ "FullscreenControl.Enter": t("enter fullscreen"),
9467
+ "FullscreenControl.Exit": t("exit fullscreen"),
9468
+ "Popup.Close": t("close popup"),
9469
+ "Map.Title": t("map"),
9470
+ "Marker.Title": t("map marker"),
9471
+ "CooperativeGesturesHandler.WindowsHelpText": t("use ctrl + scroll to zoom the map"),
9472
+ "CooperativeGesturesHandler.MacHelpText": t("use cmd + scroll to zoom the map"),
9473
+ "CooperativeGesturesHandler.MobileHelpText": t("use two fingers to move the map")
9474
+ };
9475
+ }
9476
+ function label_ctrl($root, selector, text) {
9477
+ if (!$root || !text) return;
9478
+ for (const $el of $root.querySelectorAll(selector)) {
9479
+ $el.setAttribute("title", text);
9480
+ $el.setAttribute("aria-label", text);
9481
+ }
9482
+ }
9483
+ function yui_maplibre_relocalize(map, t) {
9484
+ if (!map || typeof map.getContainer !== "function") return;
9485
+ const strings = yui_maplibre_locale(t);
9486
+ try {
9487
+ map._locale = Object.assign({}, map._locale, strings);
9488
+ } catch (e) {}
9489
+ const $c = map.getContainer();
9490
+ label_ctrl($c, ".maplibregl-ctrl-zoom-in", strings["NavigationControl.ZoomIn"]);
9491
+ label_ctrl($c, ".maplibregl-ctrl-zoom-out", strings["NavigationControl.ZoomOut"]);
9492
+ label_ctrl($c, ".maplibregl-ctrl-compass", strings["NavigationControl.ResetBearing"]);
9493
+ label_ctrl($c, ".maplibregl-ctrl-geolocate", strings["GeolocateControl.FindMyLocation"]);
9494
+ label_ctrl($c, ".maplibregl-ctrl-attrib-button", strings["AttributionControl.ToggleAttribution"]);
9495
+ label_ctrl($c, ".maplibregl-ctrl-fullscreen", strings["FullscreenControl.Enter"]);
9496
+ label_ctrl($c, ".maplibregl-popup-close-button", strings["Popup.Close"]);
9497
+ const mac = typeof navigator !== "undefined" && (navigator.userAgent || "").includes("Mac");
9498
+ const $desktop = $c.querySelector(".maplibregl-desktop-message");
9499
+ if ($desktop) $desktop.textContent = mac ? strings["CooperativeGesturesHandler.MacHelpText"] : strings["CooperativeGesturesHandler.WindowsHelpText"];
9500
+ const $mobile = $c.querySelector(".maplibregl-mobile-message");
9501
+ if ($mobile) $mobile.textContent = strings["CooperativeGesturesHandler.MobileHelpText"];
9502
+ }
9415
9503
  //#endregion
9416
9504
  //#region src/c_yui_map.js
9417
9505
  /***********************************************************************
@@ -9426,6 +9514,7 @@ var MarkerControl = class {
9426
9514
  * Constants
9427
9515
  ***************************************************************/
9428
9516
  var GCLASS_NAME$15 = "C_YUI_MAP";
9517
+ var GESTURE_HINT_MS = 2e3;
9429
9518
  /***************************************************************
9430
9519
  * Data
9431
9520
  ***************************************************************/
@@ -9452,6 +9541,7 @@ var attrs_table$15 = [
9452
9541
  ];
9453
9542
  var PRIVATE_DATA$15 = {
9454
9543
  xmap: null,
9544
+ gesture_hint_timer: null,
9455
9545
  geojson: null,
9456
9546
  resizeObserver: null,
9457
9547
  width: 0,
@@ -9476,7 +9566,8 @@ function mt_create$15(gobj) {
9476
9566
  if ($map) $map.classList.add(GCLASS_NAME$15);
9477
9567
  Object.assign(map_settings, {
9478
9568
  container: $map,
9479
- cooperativeGestures: true
9569
+ cooperativeGestures: true,
9570
+ locale: yui_maplibre_locale(t)
9480
9571
  });
9481
9572
  priv.onClick = (ev) => {
9482
9573
  onClick(gobj, ev);
@@ -9494,6 +9585,16 @@ function mt_create$15(gobj) {
9494
9585
  xtouchStart(gobj, ev);
9495
9586
  };
9496
9587
  const map = priv.xmap = new maplibregl.Map(map_settings);
9588
+ map.on("cooperativegestureprevented", () => {
9589
+ const $s = map.getCanvasContainer().querySelector(".maplibregl-cooperative-gesture-screen");
9590
+ if (!$s) return;
9591
+ $s.classList.add("MAP_GESTURE_SHOWN");
9592
+ if (priv.gesture_hint_timer) clearTimeout(priv.gesture_hint_timer);
9593
+ priv.gesture_hint_timer = setTimeout(() => {
9594
+ priv.gesture_hint_timer = null;
9595
+ $s.classList.remove("MAP_GESTURE_SHOWN");
9596
+ }, GESTURE_HINT_MS);
9597
+ });
9497
9598
  map.addControl(new maplibregl.NavigationControl());
9498
9599
  map.addControl(new MarkerControl(gobj, {}), "top-right");
9499
9600
  map.addControl(new EditControl(gobj, { showMarkerDrag: true }), "top-right");
@@ -9523,10 +9624,46 @@ function mt_create$15(gobj) {
9523
9624
  }
9524
9625
  }
9525
9626
  /***************************************************************
9627
+ * The application changed language: maplibre's own words are
9628
+ * rewritten in place, and the map's locale with them so a
9629
+ * control or a popup built later is right too.
9630
+ ***************************************************************/
9631
+ function ac_language_changed$9(gobj, event, kw, src) {
9632
+ let priv = gobj.priv;
9633
+ if (priv.xmap) yui_maplibre_relocalize(priv.xmap, t);
9634
+ return 0;
9635
+ }
9636
+ /***************************************************************
9637
+ * Framework Method: Start
9638
+ *
9639
+ * The application's LANGUAGE: what maplibre draws with words is
9640
+ * built from its `locale` when each control builds its DOM, so
9641
+ * `refresh_language()` -- which reaches what carries an i18n key
9642
+ * in OUR dom -- cannot touch any of it. The shell says when the
9643
+ * language changed and this view rewrites those strings.
9644
+ ***************************************************************/
9645
+ function mt_start$15(gobj) {
9646
+ let shell = yui_shell_of(gobj);
9647
+ if (shell) gobj_subscribe_event(shell, "EV_LANGUAGE_CHANGED", {}, gobj);
9648
+ return 0;
9649
+ }
9650
+ /***************************************************************
9651
+ * Framework Method: Stop
9652
+ ***************************************************************/
9653
+ function mt_stop$15(gobj) {
9654
+ let shell = yui_shell_of(gobj);
9655
+ if (shell) gobj_unsubscribe_event(shell, "EV_LANGUAGE_CHANGED", {}, gobj);
9656
+ return 0;
9657
+ }
9658
+ /***************************************************************
9526
9659
  * Framework Method: Destroy
9527
9660
  ***************************************************************/
9528
9661
  function mt_destroy$15(gobj) {
9529
9662
  let priv = gobj.priv;
9663
+ if (priv.gesture_hint_timer) {
9664
+ clearTimeout(priv.gesture_hint_timer);
9665
+ priv.gesture_hint_timer = null;
9666
+ }
9530
9667
  if (priv.resizeObserver) {
9531
9668
  priv.resizeObserver.disconnect();
9532
9669
  priv.resizeObserver = null;
@@ -9987,6 +10124,8 @@ function ac_hide$10(gobj, event, kw, src) {
9987
10124
  ***************************/
9988
10125
  var gmt$15 = {
9989
10126
  mt_create: mt_create$15,
10127
+ mt_start: mt_start$15,
10128
+ mt_stop: mt_stop$15,
9990
10129
  mt_destroy: mt_destroy$15
9991
10130
  };
9992
10131
  /***************************************************************
@@ -9998,6 +10137,7 @@ function create_gclass$15(gclass_name) {
9998
10137
  return -1;
9999
10138
  }
10000
10139
  __gclass__$15 = gclass_create(gclass_name, [
10140
+ ["EV_LANGUAGE_CHANGED", 0],
10001
10141
  ["EV_EDIT_MAP", 0],
10002
10142
  ["EV_CONTROL_MAP", 0],
10003
10143
  ["EV_MAP_ON_LOAD", 0],
@@ -10006,6 +10146,11 @@ function create_gclass$15(gclass_name) {
10006
10146
  ["EV_SHOW", 0],
10007
10147
  ["EV_HIDE", 0]
10008
10148
  ], [["ST_IDLE", [
10149
+ [
10150
+ "EV_LANGUAGE_CHANGED",
10151
+ ac_language_changed$9,
10152
+ null
10153
+ ],
10009
10154
  [
10010
10155
  "EV_EDIT_MAP",
10011
10156
  ac_edit_map,
@@ -20404,8 +20549,10 @@ function render_tabs(gobj, items) {
20404
20549
  class: "icon is-small yui-nav-close ml-2",
20405
20550
  "data-close-item": it.id,
20406
20551
  role: "button",
20407
- "aria-label": "close",
20408
- title: "close"
20552
+ "aria-label": t("close"),
20553
+ "data-i18n-aria-label": "close",
20554
+ title: t("close"),
20555
+ "data-i18n-title": "close"
20409
20556
  },
20410
20557
  ["i", {
20411
20558
  class: "yi-xmark",
@@ -24853,7 +25000,8 @@ function create_tabulator(gobj) {
24853
25000
  }
24854
25001
  if (write_plan(gobj).in_row_icons) columns.push({
24855
25002
  field: "_operation",
24856
- title: "Op",
25003
+ title: "",
25004
+ titleFormatter: () => t("operations"),
24857
25005
  hozAlign: "center",
24858
25006
  frozen: "right",
24859
25007
  visible: false,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yuneta/gobj-ui",
3
- "version": "7.23.110",
3
+ "version": "7.23.112",
4
4
  "type": "module",
5
5
  "main": "dist/gobj-ui.cjs.js",
6
6
  "module": "dist/gobj-ui.es.js",
package/src/c_yui_form.js CHANGED
@@ -347,7 +347,7 @@ function toolbar_button(gobj, name)
347
347
  {
348
348
  switch(name) {
349
349
  case "save":
350
- return ['button', {class: 'button p-1 button-save', title: 'save', 'aria-label': 'save', disabled: true}, [
350
+ return ['button', {class: 'button p-1 button-save', title: t('save'), 'data-i18n-title': 'save', 'aria-label': t('save'), 'data-i18n-aria-label': 'save', disabled: true}, [
351
351
  ['span', {class: 'icon m-0'}, '<i class="yi-floppy-disk"></i>'],
352
352
  ['span', {class: 'is-hidden-mobile pl-1 pr-1', i18n: 'save'}, 'save']
353
353
  ], {
@@ -357,7 +357,7 @@ function toolbar_button(gobj, name)
357
357
  }
358
358
  }];
359
359
  case "undo":
360
- return ['button', {class: 'button p-1 button-undo', title: 'undo', 'aria-label': 'undo', disabled: true}, [
360
+ return ['button', {class: 'button p-1 button-undo', title: t('undo'), 'data-i18n-title': 'undo', 'aria-label': t('undo'), 'data-i18n-aria-label': 'undo', disabled: true}, [
361
361
  ['span', {class: 'icon m-0'}, '<i class="yi-arrow-rotate-left"></i>'],
362
362
  ['span', {class: 'is-hidden-mobile pl-1 pr-1', i18n: 'undo'}, 'undo']
363
363
  ], {
@@ -367,7 +367,7 @@ function toolbar_button(gobj, name)
367
367
  }
368
368
  }];
369
369
  case "clear":
370
- return ['button', {class: 'button p-1 button-clear', title: 'clear', 'aria-label': 'clear'}, [
370
+ return ['button', {class: 'button p-1 button-clear', title: t('clear'), 'data-i18n-title': 'clear', 'aria-label': t('clear'), 'data-i18n-aria-label': 'clear'}, [
371
371
  ['span', {class: 'icon m-0'}, '<i class="yi-broom-wide"></i>'],
372
372
  ['span', {class: 'is-hidden-mobile pl-1 pr-1', i18n: 'clear'}, 'clear']
373
373
  ], {
@@ -377,7 +377,7 @@ function toolbar_button(gobj, name)
377
377
  }
378
378
  }];
379
379
  case "copy":
380
- return ['button', {class: 'button p-1 button-copy', title: 'copy', 'aria-label': 'copy'}, [
380
+ return ['button', {class: 'button p-1 button-copy', title: t('copy'), 'data-i18n-title': 'copy', 'aria-label': t('copy'), 'data-i18n-aria-label': 'copy'}, [
381
381
  ['span', {class: 'icon m-0'}, '<i class="yi-copy"></i>'],
382
382
  ['span', {class: 'is-hidden-mobile pl-1 pr-1', i18n: 'copy'}, 'copy']
383
383
  ], {click: function(evt) {
@@ -386,7 +386,7 @@ function toolbar_button(gobj, name)
386
386
  }
387
387
  }];
388
388
  case "paste":
389
- return ['button', {class: 'button p-1 button-paste', title: 'paste', 'aria-label': 'paste'}, [
389
+ return ['button', {class: 'button p-1 button-paste', title: t('paste'), 'data-i18n-title': 'paste', 'aria-label': t('paste'), 'data-i18n-aria-label': 'paste'}, [
390
390
  ['span', {class: 'icon m-0'}, '<i class="yi-paste"></i>'],
391
391
  ['span', {class: 'is-hidden-mobile pl-1 pr-1', i18n: 'paste'}, 'paste']
392
392
  ], {click: async function(evt) {
@@ -2011,7 +2011,10 @@ function template2columns(gobj, columns, template, sub_elements)
2011
2011
  format: "dd/MM/yyyy hh:mm", // the format of the date value stored in the cell
2012
2012
  verticalNavigation: "table", //navigate cursor around table without changing the value
2013
2013
  elementAttributes: {
2014
- title:"slide bar to choose option" // custom tooltip
2014
+ /* Tabulator writes this attribute once, when the
2015
+ * editor opens, so it is translated then -- which
2016
+ * is also when it is read. */
2017
+ title: t("slide bar to choose option")
2015
2018
  }
2016
2019
  };
2017
2020
  switch(field_desc.real_type) {
package/src/c_yui_map.css CHANGED
@@ -33,3 +33,29 @@
33
33
  .xmap .column {
34
34
  padding: 0 !important;
35
35
  }
36
+
37
+ /*
38
+ * The cooperative-gesture notice: "Use Ctrl + scroll to zoom the map".
39
+ *
40
+ * maplibre's own sheet shows it for 100ms and lets it FADE for a second
41
+ * more (`transition: opacity 1s ease 1s`). Nothing here has transitions,
42
+ * so that fade is cut -- and with it the only thing that made the notice
43
+ * readable, since 100ms is not reading time. `c_yui_map.js` holds it by
44
+ * the clock instead: it appears and disappears at once, and stands still
45
+ * in between.
46
+ */
47
+ .maplibregl-cooperative-gesture-screen,
48
+ .maplibregl-cooperative-gesture-screen.maplibregl-show {
49
+ transition: none !important;
50
+ }
51
+
52
+ .maplibregl-cooperative-gesture-screen.MAP_GESTURE_SHOWN {
53
+ opacity: 1;
54
+ }
55
+
56
+ /* 1.4em leaves the notice in four lines on the small map of a card. It
57
+ * is an instruction, not a headline. */
58
+ .maplibregl-cooperative-gesture-screen {
59
+ font-size: 1rem;
60
+ text-align: center;
61
+ }
package/src/c_yui_map.js CHANGED
@@ -29,6 +29,7 @@ import {
29
29
  gobj_create_service,
30
30
  gobj_start,
31
31
  gobj_name,
32
+ gobj_unsubscribe_event,
32
33
  } from "@yuneta/gobj-js";
33
34
 
34
35
  import "maplibre-gl/dist/maplibre-gl.css"; // Import MapLibre styles
@@ -36,9 +37,15 @@ import * as maplibregl from "maplibre-gl"; // MapLibre GL JS 6 is ESM-only, no d
36
37
 
37
38
  import {
38
39
  EditControl,
39
- MarkerControl
40
+ MarkerControl,
41
+ yui_maplibre_locale,
42
+ yui_maplibre_relocalize
40
43
  } from "./lib_maplibre.js";
41
44
 
45
+ import {t} from "i18next";
46
+
47
+ import {yui_shell_of} from "./c_yui_shell.js";
48
+
42
49
  import "./c_yui_map.css"; // Must be in index.js ?
43
50
 
44
51
  /***************************************************************
@@ -46,6 +53,9 @@ import "./c_yui_map.css"; // Must be in index.js ?
46
53
  ***************************************************************/
47
54
  const GCLASS_NAME = "C_YUI_MAP";
48
55
 
56
+ /* How long the cooperative-gesture notice stays up, in ms. */
57
+ const GESTURE_HINT_MS = 2000;
58
+
49
59
  /***************************************************************
50
60
  * Data
51
61
  ***************************************************************/
@@ -74,6 +84,7 @@ SDATA_END()
74
84
 
75
85
  let PRIVATE_DATA = {
76
86
  xmap: null,
87
+ gesture_hint_timer: null, /* keeps the gesture notice up long enough */
77
88
  geojson: null,
78
89
  resizeObserver: null,
79
90
  width: 0, // map size, data got from resize observer
@@ -132,6 +143,13 @@ function mt_create(gobj)
132
143
  * default is a suggestion -- the demo passes `map_settings` and
133
144
  * never saw it. This is the house gesture, not a suggestion. */
134
145
  cooperativeGestures: true,
146
+ /* maplibre draws words of its own -- the zoom tooltips, the
147
+ * geolocate button, the attribution toggle and the notice that
148
+ * teaches the gesture above -- and they came out in ITS
149
+ * English inside a Spanish app. `locale` is read once, when
150
+ * each control builds its DOM, so the language CHANGE is the
151
+ * other half, in ac_language_changed. */
152
+ locale: yui_maplibre_locale(t),
135
153
  });
136
154
 
137
155
  /*-----------------------------*
@@ -158,6 +176,35 @@ function mt_create(gobj)
158
176
  *-----------------------------*/
159
177
  const map = priv.xmap = new maplibregl.Map(map_settings);
160
178
 
179
+ /* HOW LONG THE NOTICE STAYS UP.
180
+ *
181
+ * maplibre shows it for 100ms and lets it FADE for a second more
182
+ * (`transition: opacity 1s ease 1s`). Nothing in this GUI has
183
+ * transitions, so that fade is cut -- and with it the only thing
184
+ * that made the notice readable, because 100ms is not reading
185
+ * time. It is held by the clock instead: on and off at once, and
186
+ * still in between for as long as it takes to read it.
187
+ *
188
+ * In maplibre's callback and not through the machine, for the same
189
+ * reason as the zoom readout: it is not an action, it is the map
190
+ * acknowledging a gesture it refused, and one wheel fires it
191
+ * dozens of times. */
192
+ map.on("cooperativegestureprevented", () => {
193
+ const $s = map.getCanvasContainer()
194
+ .querySelector(".maplibregl-cooperative-gesture-screen");
195
+ if(!$s) {
196
+ return;
197
+ }
198
+ $s.classList.add("MAP_GESTURE_SHOWN");
199
+ if(priv.gesture_hint_timer) {
200
+ clearTimeout(priv.gesture_hint_timer);
201
+ }
202
+ priv.gesture_hint_timer = setTimeout(() => {
203
+ priv.gesture_hint_timer = null;
204
+ $s.classList.remove("MAP_GESTURE_SHOWN");
205
+ }, GESTURE_HINT_MS);
206
+ });
207
+
161
208
  /*-----------------------------*
162
209
  * Controls
163
210
  *-----------------------------*/
@@ -219,6 +266,51 @@ function mt_create(gobj)
219
266
  }
220
267
  }
221
268
 
269
+ /***************************************************************
270
+ * The application changed language: maplibre's own words are
271
+ * rewritten in place, and the map's locale with them so a
272
+ * control or a popup built later is right too.
273
+ ***************************************************************/
274
+ function ac_language_changed(gobj, event, kw, src)
275
+ {
276
+ let priv = gobj.priv;
277
+
278
+ if(priv.xmap) {
279
+ yui_maplibre_relocalize(priv.xmap, t);
280
+ }
281
+ return 0;
282
+ }
283
+
284
+ /***************************************************************
285
+ * Framework Method: Start
286
+ *
287
+ * The application's LANGUAGE: what maplibre draws with words is
288
+ * built from its `locale` when each control builds its DOM, so
289
+ * `refresh_language()` -- which reaches what carries an i18n key
290
+ * in OUR dom -- cannot touch any of it. The shell says when the
291
+ * language changed and this view rewrites those strings.
292
+ ***************************************************************/
293
+ function mt_start(gobj)
294
+ {
295
+ let shell = yui_shell_of(gobj);
296
+ if(shell) {
297
+ gobj_subscribe_event(shell, "EV_LANGUAGE_CHANGED", {}, gobj);
298
+ }
299
+ return 0;
300
+ }
301
+
302
+ /***************************************************************
303
+ * Framework Method: Stop
304
+ ***************************************************************/
305
+ function mt_stop(gobj)
306
+ {
307
+ let shell = yui_shell_of(gobj);
308
+ if(shell) {
309
+ gobj_unsubscribe_event(shell, "EV_LANGUAGE_CHANGED", {}, gobj);
310
+ }
311
+ return 0;
312
+ }
313
+
222
314
  /***************************************************************
223
315
  * Framework Method: Destroy
224
316
  ***************************************************************/
@@ -226,6 +318,10 @@ function mt_destroy(gobj)
226
318
  {
227
319
  let priv = gobj.priv;
228
320
 
321
+ if(priv.gesture_hint_timer) {
322
+ clearTimeout(priv.gesture_hint_timer);
323
+ priv.gesture_hint_timer = null;
324
+ }
229
325
  if(priv.resizeObserver) {
230
326
  priv.resizeObserver.disconnect();
231
327
  priv.resizeObserver = null;
@@ -934,6 +1030,8 @@ function ac_hide(gobj, event, kw, src)
934
1030
  *---------------------------------------------*/
935
1031
  const gmt = {
936
1032
  mt_create: mt_create,
1033
+ mt_start: mt_start,
1034
+ mt_stop: mt_stop,
937
1035
  mt_destroy: mt_destroy
938
1036
  };
939
1037
 
@@ -952,6 +1050,7 @@ function create_gclass(gclass_name)
952
1050
  *---------------------------------------------*/
953
1051
  const states = [
954
1052
  ["ST_IDLE", [
1053
+ ["EV_LANGUAGE_CHANGED", ac_language_changed, null],
955
1054
  ["EV_EDIT_MAP", ac_edit_map, null],
956
1055
  ["EV_CONTROL_MAP", ac_control_map, null],
957
1056
  ["EV_MAP_ON_LOAD", ac_map_on_load, null],
@@ -966,6 +1065,7 @@ function create_gclass(gclass_name)
966
1065
  * Events
967
1066
  *---------------------------------------------*/
968
1067
  const event_types = [
1068
+ ["EV_LANGUAGE_CHANGED", 0],
969
1069
  ["EV_EDIT_MAP", 0],
970
1070
  ["EV_CONTROL_MAP", 0],
971
1071
  ["EV_MAP_ON_LOAD", 0],
package/src/c_yui_nav.js CHANGED
@@ -74,6 +74,8 @@ import {
74
74
  createElement2, empty_string, is_array, is_object, is_string,
75
75
  } from "@yuneta/gobj-js";
76
76
 
77
+ import {t} from "i18next";
78
+
77
79
  import { cards_grid_descriptor } from "./nav_cards_helpers.js";
78
80
  import {
79
81
  BULMA_BP_ORDER,
@@ -407,7 +409,8 @@ function render_tabs(gobj, items)
407
409
  if(it.closable) {
408
410
  children.push(["span", {class: "icon is-small yui-nav-close ml-2",
409
411
  "data-close-item": it.id, role: "button",
410
- "aria-label": "close", title: "close"},
412
+ "aria-label": t("close"), "data-i18n-aria-label": "close",
413
+ title: t("close"), "data-i18n-title": "close"},
411
414
  ["i", {class: "yi-xmark", "aria-hidden":"true"}]]);
412
415
  }
413
416
  let a_attrs = {
@@ -1384,7 +1384,13 @@ function create_tabulator(gobj)
1384
1384
  if(with_in_row_edit_icons) {
1385
1385
  columns.push({
1386
1386
  field: '_operation',
1387
- title: 'Op',
1387
+ /* A FORMATTER and not a `title`, like every other column of
1388
+ * this table: a language change re-runs `setColumns()` over
1389
+ * the SAME definitions, so a title decided when they were
1390
+ * built -- `'Op'`, in English and abbreviated -- is frozen
1391
+ * there for the life of the view. */
1392
+ title: '',
1393
+ titleFormatter: () => t('operations'),
1388
1394
  hozAlign: 'center',
1389
1395
  frozen: "right",
1390
1396
  visible: false,
@@ -61,7 +61,9 @@ class EditControl {
61
61
  {
62
62
  class: 'button is-small is-flex is-align-items-center is-justify-content-center',
63
63
  title: t('maplibre.drag_mark'),
64
+ "data-i18n-title": 'maplibre.drag_mark',
64
65
  "aria-label": t('maplibre.drag_mark'),
66
+ "data-i18n-aria-label": 'maplibre.drag_mark',
65
67
  },
66
68
  parseSVG(`
67
69
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="22" height="22" fill="#CCCCCC"><path d="M273 7c-9.4-9.4-24.6-9.4-33.9 0L167 79c-9.4 9.4-9.4 24.6 0 33.9s24.6 9.4 33.9 0l31-31L232 232 81.9 232l31-31c9.4-9.4 9.4-24.6 0-33.9s-24.6-9.4-33.9 0L7 239c-9.4 9.4-9.4 24.6 0 33.9l72 72c9.4 9.4 24.6 9.4 33.9 0s9.4-24.6 0-33.9l-31-31L232 280l0 150.1-31-31c-9.4-9.4-24.6-9.4-33.9 0s-9.4 24.6 0 33.9l72 72c9.4 9.4 24.6 9.4 33.9 0l72-72c9.4-9.4 9.4-24.6 0-33.9s-24.6-9.4-33.9 0l-31 31L280 280l150.1 0-31 31c-9.4 9.4-9.4 24.6 0 33.9s24.6 9.4 33.9 0l72-72c9.4-9.4 9.4-24.6 0-33.9l-72-72c-9.4-9.4-24.6-9.4-33.9 0s-9.4 24.6 0 33.9l31 31L280 232l0-150.1 31 31c9.4 9.4 24.6 9.4 33.9 0s9.4-24.6 0-33.9L273 7z"/></svg>
@@ -144,7 +146,9 @@ class MarkerControl {
144
146
  {
145
147
  class: 'button is-small is-flex is-align-items-center is-justify-content-center',
146
148
  title: t('maplibre.center_map'),
149
+ "data-i18n-title": 'maplibre.center_map',
147
150
  "aria-label": t('maplibre.center_map'),
151
+ "data-i18n-aria-label": 'maplibre.center_map',
148
152
  },
149
153
  parseSVG(`
150
154
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512" width="22" height="22"><path d="M15 15C24.4 5.7 39.6 5.7 49 15l63 63L112 40c0-13.3 10.7-24 24-24s24 10.7 24 24l0 96c0 13.3-10.7 24-24 24l-96 0c-13.3 0-24-10.7-24-24s10.7-24 24-24l38.1 0L15 49C5.7 39.6 5.7 24.4 15 15zM133.5 243.9C158.6 193.6 222.7 112 320 112s161.4 81.6 186.5 131.9c3.8 7.6 3.8 16.5 0 24.2C481.4 318.4 417.3 400 320 400s-161.4-81.6-186.5-131.9c-3.8-7.6-3.8-16.5 0-24.2zM320 320a64 64 0 1 0 0-128 64 64 0 1 0 0 128zM591 15c9.4-9.4 24.6-9.4 33.9 0s9.4 24.6 0 33.9l-63 63 38.1 0c13.3 0 24 10.7 24 24s-10.7 24-24 24l-96 0c-13.3 0-24-10.7-24-24l0-96c0-13.3 10.7-24 24-24s24 10.7 24 24l0 38.1 63-63zM15 497c-9.4-9.4-9.4-24.6 0-33.9l63-63L40 400c-13.3 0-24-10.7-24-24s10.7-24 24-24l96 0c13.3 0 24 10.7 24 24l0 96c0 13.3-10.7 24-24 24s-24-10.7-24-24l0-38.1L49 497c-9.4 9.4-24.6 9.4-33.9 0zm576 0l-63-63 0 38.1c0 13.3-10.7 24-24 24s-24-10.7-24-24l0-96c0-13.3 10.7-24 24-24l96 0c13.3 0 24 10.7 24 24s-10.7 24-24 24l-38.1 0 63 63c9.4 9.4 9.4 24.6 0 33.9s-24.6 9.4-33.9 0z"/></svg>
@@ -166,7 +170,9 @@ class MarkerControl {
166
170
  {
167
171
  class: 'button is-small is-flex is-align-items-center is-justify-content-center',
168
172
  title: t('maplibre.user_location'),
173
+ "data-i18n-title": 'maplibre.user_location',
169
174
  "aria-label": t('maplibre.user_location'),
175
+ "data-i18n-aria-label": 'maplibre.user_location',
170
176
  },
171
177
  parseSVG(`
172
178
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="22" height="22" fill="#CCCCCC"><path d="M256 0c17.7 0 32 14.3 32 32l0 34.7C368.4 80.1 431.9 143.6 445.3 224l34.7 0c17.7 0 32 14.3 32 32s-14.3 32-32 32l-34.7 0C431.9 368.4 368.4 431.9 288 445.3l0 34.7c0 17.7-14.3 32-32 32s-32-14.3-32-32l0-34.7C143.6 431.9 80.1 368.4 66.7 288L32 288c-17.7 0-32-14.3-32-32s14.3-32 32-32l34.7 0C80.1 143.6 143.6 80.1 224 66.7L224 32c0-17.7 14.3-32 32-32zM128 256a128 128 0 1 0 256 0 128 128 0 1 0 -256 0zm128-80a80 80 0 1 1 0 160 80 80 0 1 1 0-160z"/></svg>
@@ -215,10 +221,116 @@ class MarkerControl {
215
221
  }
216
222
  }
217
223
 
224
+
225
+ /***********************************************************************
226
+ * MAPLIBRE'S OWN CHROME, IN THE APP'S LANGUAGE
227
+ *
228
+ * Everything maplibre draws with words -- the zoom tooltips, the
229
+ * geolocate button, the attribution toggle, a popup's close, and the
230
+ * notice that teaches the Ctrl + wheel gesture -- comes from its
231
+ * `locale`, an option merged over its own English defaults at
232
+ * construction. So a map in a Spanish app was saying *"Zoom in"* and
233
+ * *"Use Ctrl + scroll to zoom the map"*, which is the same rule this
234
+ * GUI applies to every other string.
235
+ *
236
+ * Two halves, because maplibre reads its strings ONCE, when each
237
+ * control builds its DOM:
238
+ *
239
+ * `yui_maplibre_locale(t)` the `locale` option, for the map's
240
+ * first paint;
241
+ * `yui_maplibre_relocalize()` after a language change, which is
242
+ * the half a `locale` alone cannot
243
+ * do -- it writes the strings into
244
+ * the DOM already drawn, and updates
245
+ * the map's locale so anything built
246
+ * later is right too.
247
+ *
248
+ * The scale units (`km`, `mi`, `nm`) are symbols and are left alone;
249
+ * the MapLibre logo keeps its name, which is a brand.
250
+ ***********************************************************************/
251
+ function yui_maplibre_locale(t)
252
+ {
253
+ return {
254
+ "NavigationControl.ZoomIn": t("zoom in"),
255
+ "NavigationControl.ZoomOut": t("zoom out"),
256
+ "NavigationControl.ResetBearing": t("drag to rotate the map, click to reset north"),
257
+ "GeolocateControl.FindMyLocation": t("find my location"),
258
+ "GeolocateControl.LocationNotAvailable": t("location not available"),
259
+ "AttributionControl.ToggleAttribution": t("toggle attribution"),
260
+ "AttributionControl.MapFeedback": t("map feedback"),
261
+ "FullscreenControl.Enter": t("enter fullscreen"),
262
+ "FullscreenControl.Exit": t("exit fullscreen"),
263
+ "Popup.Close": t("close popup"),
264
+ "Map.Title": t("map"),
265
+ "Marker.Title": t("map marker"),
266
+ "CooperativeGesturesHandler.WindowsHelpText": t("use ctrl + scroll to zoom the map"),
267
+ "CooperativeGesturesHandler.MacHelpText": t("use cmd + scroll to zoom the map"),
268
+ "CooperativeGesturesHandler.MobileHelpText": t("use two fingers to move the map"),
269
+ };
270
+ }
271
+
272
+ /* One drawn control: its tooltip and its aria-label say the same
273
+ * thing, and a screen reader needs the second even when the first is
274
+ * what a pointer finds. */
275
+ function label_ctrl($root, selector, text)
276
+ {
277
+ if(!$root || !text) {
278
+ return;
279
+ }
280
+ for(const $el of $root.querySelectorAll(selector)) {
281
+ $el.setAttribute("title", text);
282
+ $el.setAttribute("aria-label", text);
283
+ }
284
+ }
285
+
286
+ function yui_maplibre_relocalize(map, t)
287
+ {
288
+ if(!map || typeof map.getContainer !== "function") {
289
+ return;
290
+ }
291
+ const strings = yui_maplibre_locale(t);
292
+
293
+ /* The map's own table first: a control added later (or a popup
294
+ * opened later) reads it when it builds itself. */
295
+ try {
296
+ map._locale = Object.assign({}, map._locale, strings);
297
+ } catch(e) {
298
+ /* a maplibre that keeps its locale elsewhere: the DOM below
299
+ * still gets translated, which is what is on screen */
300
+ }
301
+
302
+ const $c = map.getContainer();
303
+ label_ctrl($c, ".maplibregl-ctrl-zoom-in", strings["NavigationControl.ZoomIn"]);
304
+ label_ctrl($c, ".maplibregl-ctrl-zoom-out", strings["NavigationControl.ZoomOut"]);
305
+ label_ctrl($c, ".maplibregl-ctrl-compass", strings["NavigationControl.ResetBearing"]);
306
+ label_ctrl($c, ".maplibregl-ctrl-geolocate", strings["GeolocateControl.FindMyLocation"]);
307
+ label_ctrl($c, ".maplibregl-ctrl-attrib-button", strings["AttributionControl.ToggleAttribution"]);
308
+ label_ctrl($c, ".maplibregl-ctrl-fullscreen", strings["FullscreenControl.Enter"]);
309
+ label_ctrl($c, ".maplibregl-popup-close-button", strings["Popup.Close"]);
310
+
311
+ /* The notice of the cooperative gesture: two lines, one for a
312
+ * pointer and one for a finger, built by `_setupUI()` as
313
+ * `.maplibregl-desktop-message` / `.maplibregl-mobile-message`. */
314
+ const mac = (typeof navigator !== "undefined" &&
315
+ (navigator.userAgent || "").includes("Mac"));
316
+ const $desktop = $c.querySelector(".maplibregl-desktop-message");
317
+ if($desktop) {
318
+ $desktop.textContent = mac
319
+ ? strings["CooperativeGesturesHandler.MacHelpText"]
320
+ : strings["CooperativeGesturesHandler.WindowsHelpText"];
321
+ }
322
+ const $mobile = $c.querySelector(".maplibregl-mobile-message");
323
+ if($mobile) {
324
+ $mobile.textContent = strings["CooperativeGesturesHandler.MobileHelpText"];
325
+ }
326
+ }
327
+
218
328
  //=======================================================================
219
329
  // Expose the class via the global object
220
330
  //=======================================================================
221
331
  export {
222
332
  EditControl,
223
- MarkerControl
333
+ MarkerControl,
334
+ yui_maplibre_locale,
335
+ yui_maplibre_relocalize
224
336
  };