This is an automated email from the ASF dual-hosted git repository.

desruisseaux pushed a commit to branch geoapi-4.0
in repository https://gitbox.apache.org/repos/asf/sis.git

commit 7d3d5c36483c43fbd191f5683b50fdb9ae61231a
Author: Martin Desruisseaux <[email protected]>
AuthorDate: Fri Sep 12 14:09:46 2025 +0200

    Fix warnings emitted during the parsing of units of measurement in some 
netCDF files.
    contains also a dependency upgrade and fix in the metadata display in GUI.
---
 .../sis/openoffice/ReferencingFunctions.java       |  4 +-
 .../org/apache/sis/openoffice/package-info.java    |  2 +-
 .../apache/sis/storage/netcdf/MetadataReader.java  |  1 +
 .../org/apache/sis/storage/netcdf/base/Axis.java   |  2 +-
 .../apache/sis/storage/netcdf/base/AxisType.java   | 32 ++++++-----
 .../apache/sis/storage/netcdf/base/FeatureSet.java |  2 +-
 .../storage/netcdf/base/VariableTransformer.java   |  2 +-
 .../sis/storage/netcdf/classic/GridInfo.java       |  2 +-
 .../sis/storage/netcdf/ucar/GridWrapper.java       |  2 +-
 .../sis/storage/netcdf/ucar/VariableWrapper.java   |  6 +-
 .../org/apache/sis/measure/UnitAliases.properties  |  8 +--
 .../main/org/apache/sis/measure/UnitFormat.java    | 44 +++++++++------
 .../apache/sis/measure/UnitNames_en_US.properties  |  3 +
 .../org/apache/sis/util/resources/Vocabulary.java  |  5 ++
 .../sis/util/resources/Vocabulary.properties       |  1 +
 .../sis/util/resources/Vocabulary_fr.properties    |  1 +
 .../org/apache/sis/measure/UnitFormatTest.java     | 66 +++++++++++++---------
 netbeans-project/ivy.xml                           |  2 +-
 .../apache/sis/gui/metadata/MetadataSummary.java   | 19 +++++--
 .../sis/gui/metadata/RepresentationInfo.java       | 15 +++--
 settings.gradle.kts                                |  2 +-
 21 files changed, 136 insertions(+), 85 deletions(-)

diff --git 
a/endorsed/src/org.apache.sis.openoffice/main/org/apache/sis/openoffice/ReferencingFunctions.java
 
b/endorsed/src/org.apache.sis.openoffice/main/org/apache/sis/openoffice/ReferencingFunctions.java
index 21cfa71560..1cf4c66e88 100644
--- 
a/endorsed/src/org.apache.sis.openoffice/main/org/apache/sis/openoffice/ReferencingFunctions.java
+++ 
b/endorsed/src/org.apache.sis.openoffice/main/org/apache/sis/openoffice/ReferencingFunctions.java
@@ -55,9 +55,10 @@ import org.opengis.referencing.ObjectDomain;
  *
  * @author  Richard Deplanque (IRD)
  * @author  Martin Desruisseaux (IRD, Geomatys)
- * @version 0.8
+ * @version 1.5
  * @since   0.8
  */
+@SuppressWarnings("UseSpecificCatch")
 public class ReferencingFunctions extends CalcAddins implements XReferencing {
     /**
      * The name for the registration of this component.
@@ -202,7 +203,6 @@ public class ReferencingFunctions extends CalcAddins 
implements XReferencing {
      */
     @Override
     public String getScope(final String codeOrPath) {
-        final Object value;
         try {
             final IdentifiedObject object = getIdentifiedObject(codeOrPath, 
null);
             for (final ObjectDomain domain : object.getDomains()) {
diff --git 
a/endorsed/src/org.apache.sis.openoffice/main/org/apache/sis/openoffice/package-info.java
 
b/endorsed/src/org.apache.sis.openoffice/main/org/apache/sis/openoffice/package-info.java
index 8e0786e80c..565f8a8566 100644
--- 
a/endorsed/src/org.apache.sis.openoffice/main/org/apache/sis/openoffice/package-info.java
+++ 
b/endorsed/src/org.apache.sis.openoffice/main/org/apache/sis/openoffice/package-info.java
@@ -25,7 +25,7 @@
  * See {@code 
endorsed/src/org.apache.sis.openoffice/bundle/build-instruction.html} for more 
information.</p>
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
- * @version 0.8
+ * @version 1.5
  * @since   0.8
  */
 package org.apache.sis.openoffice;
diff --git 
a/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/MetadataReader.java
 
b/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/MetadataReader.java
index 60b84000e1..46f308255b 100644
--- 
a/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/MetadataReader.java
+++ 
b/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/MetadataReader.java
@@ -691,6 +691,7 @@ split:  while ((start = 
CharSequences.skipLeadingWhitespaces(value, start, lengt
      * @throws ArithmeticException if the size of an axis exceeds {@link 
Integer#MAX_VALUE}, or other overflow occurs.
      */
     private void addSpatialRepresentationInfo(final Axis[] axes) throws 
IOException, DataStoreException {
+        newGridRepresentation(GridType.UNSPECIFIED);
         for (int i=0; i<axes.length; i++) {
             final Axis axis = axes[i];
             /*
diff --git 
a/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/base/Axis.java
 
b/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/base/Axis.java
index 5057c537b6..0b41178fa9 100644
--- 
a/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/base/Axis.java
+++ 
b/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/base/Axis.java
@@ -170,7 +170,7 @@ public final class Axis extends NamedElement {
      */
     Axis(final Variable coordinates) {
         this.coordinates = coordinates;
-        abbreviation = AxisType.abbreviation(coordinates);
+        abbreviation = AxisType.abbreviation(coordinates, true);
         final AxisDirection dir = direction(coordinates.getUnitsString());
         direction = (dir != null) ? dir : 
AxisDirections.fromAbbreviation(abbreviation);
         gridDimensionIndices = null;
diff --git 
a/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/base/AxisType.java
 
b/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/base/AxisType.java
index fca5b97b5c..94e7a073e1 100644
--- 
a/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/base/AxisType.java
+++ 
b/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/base/AxisType.java
@@ -118,12 +118,13 @@ public enum AxisType {
      * Returns the axis type (identified by its abbreviation) for the given 
axis, or 0 if unknown.
      * The returned code is one of the controlled vocabulary documented in 
{@link Axis#abbreviation}.
      *
-     * @param  axis  axis for which to get an abbreviation.
+     * @param  axis     axis for which to get an abbreviation.
+     * @param  useUnit  whether this method is allowed to check the unit of 
measurement.
      * @return abbreviation for the given axis, or 0 if none.
      *
      * @see <a href="https://issues.apache.org/jira/browse/SIS-552";>SIS-552</a>
      */
-    public static char abbreviation(final Variable axis) {
+    public static char abbreviation(final Variable axis, final boolean 
useUnit) {
         /*
          * In Apache SIS implementation, the abbreviation determines the axis 
type. If a "_CoordinateAxisType" attribute
          * exists, il will have precedence over all other heuristic rules in 
this method because it is the most specific
@@ -151,7 +152,7 @@ public enum AxisType {
                      * already verified by Axis constructor. By checking the 
variable attributes first, we give a chance
                      * to Axis constructor to report a warning if there is an 
inconsistency.
                      */
-                    if (Units.isAngular(axis.getUnit())) {
+                    if (useUnit && Units.isAngular(axis.getUnit())) {
                         final AxisDirection direction = 
AxisDirections.absolute(Axis.direction(axis.getUnitsString()));
                         if (direction == AxisDirection.EAST) {
                             return 'λ';
@@ -166,16 +167,15 @@ public enum AxisType {
                     abbreviation = abbreviation(axis.getName());
                     if (fallback == null) fallback = abbreviation;
                     if (isNullOrAmbiguous(abbreviation)) {
-                        final Unit<?> unit = axis.getUnit();
-                        if (Units.isTemporal(unit)) {
-                            return 't';
-                        } else if (Units.isPressure(unit)) {
-                            return 'z';
-                        } else if (fallback != null) {
-                            return fallback;
-                        } else {
-                            return 0;
+                        if (useUnit) {
+                            final Unit<?> unit = axis.getUnit();
+                            if (Units.isTemporal(unit)) {
+                                return 't';
+                            } else if (Units.isPressure(unit)) {
+                                return 'z';
+                            }
                         }
+                        return (fallback != null) ? fallback : 0;
                     }
                 }
             }
@@ -185,9 +185,13 @@ public enum AxisType {
 
     /**
      * Returns the enumeration value for the given variable, or {@code null} 
if none.
+     *
+     * @param  axis     axis for which to get an enumeration value.
+     * @param  useUnit  whether this method is allowed to check the unit of 
measurement.
+     * @return enumeration value for the given axis, or {@code null} if none.
      */
-    static AxisType valueOf(final Variable axis) {
-        final char abbreviation = abbreviation(axis);
+    static AxisType valueOf(final Variable axis, final boolean useUnit) {
+        final char abbreviation = abbreviation(axis, useUnit);
         return (abbreviation != 0) ? VALUES.get(abbreviation) : null;
     }
 }
diff --git 
a/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/base/FeatureSet.java
 
b/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/base/FeatureSet.java
index dd5789ef2a..4bd81d41ca 100644
--- 
a/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/base/FeatureSet.java
+++ 
b/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/base/FeatureSet.java
@@ -432,7 +432,7 @@ final class FeatureSet extends DiscreteSampling {
              * We handle separately the axes having coordinates provided by 
static and dynamic properties.
              * We will decide at the end of this loop which one of those two 
groups to use.
              */
-            final AxisType axisType = AxisType.valueOf(data);
+            final AxisType axisType = AxisType.valueOf(data, true);
             if (axisType != null) {
                 final Variable previous = (dynamic ? trajectory : 
coordinates).putIfAbsent(axisType, data);
                 if (previous != null) {
diff --git 
a/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/base/VariableTransformer.java
 
b/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/base/VariableTransformer.java
index a40600866b..8eff98382b 100644
--- 
a/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/base/VariableTransformer.java
+++ 
b/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/base/VariableTransformer.java
@@ -191,7 +191,7 @@ final class VariableTransformer {
                 matchers = new Matcher[candidates.length];
             }
             for (final UnitPattern candidate : candidates) {
-                if (!candidate.requireTimeAxis || AxisType.valueOf(variable) 
== AxisType.T) {
+                if (!candidate.requireTimeAxis || AxisType.valueOf(variable, 
false) == AxisType.T) {
                     Matcher matcher = matchers[candidate.ordinal()];
                     if (matcher == null) {
                         matcher = candidate.pattern.matcher(units);
diff --git 
a/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/classic/GridInfo.java
 
b/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/classic/GridInfo.java
index 1596467eac..3f1b9d97f2 100644
--- 
a/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/classic/GridInfo.java
+++ 
b/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/classic/GridInfo.java
@@ -221,7 +221,7 @@ next:       for (final String name : axisNames) {
                     }
                 }
             }
-            final char abbreviation = AxisType.abbreviation(axis);
+            final char abbreviation = AxisType.abbreviation(axis, true);
             axes[targetDim] = new Axis(abbreviation, 
axis.getAttributeAsString(CF.POSITIVE), indices, sizes, i, axis);
         }
         return axes;
diff --git 
a/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/ucar/GridWrapper.java
 
b/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/ucar/GridWrapper.java
index e893ac60e0..d2fe64b757 100644
--- 
a/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/ucar/GridWrapper.java
+++ 
b/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/ucar/GridWrapper.java
@@ -280,7 +280,7 @@ next:       for (final String name : axisNames) {
                 case RadialDistance:  abbreviation = 'r'; break;    // 
Geocentric radius
             }
             if (abbreviation == 0) {
-                abbreviation = 
org.apache.sis.storage.netcdf.base.AxisType.abbreviation(wrapper);
+                abbreviation = 
org.apache.sis.storage.netcdf.base.AxisType.abbreviation(wrapper, true);
             }
             /*
              * Get the grid dimensions (part of the "domain" in UCAR 
terminology) used for computing
diff --git 
a/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/ucar/VariableWrapper.java
 
b/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/ucar/VariableWrapper.java
index 24a5cb3753..7cc300f3dd 100644
--- 
a/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/ucar/VariableWrapper.java
+++ 
b/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/ucar/VariableWrapper.java
@@ -171,7 +171,7 @@ final class VariableWrapper extends 
org.apache.sis.storage.netcdf.base.Variable
              * "2 hours since 1970-01-01 00:00:00". If there is no such 
number, then the two methods
              * are equivalent. It is not clear that adding such number is the 
right thing to do.
              */
-            final DateUnit temporal = new DateUnit(symbols);
+            final var temporal = new DateUnit(symbols);
             epoch = temporal.getDateOrigin().toInstant();
             return 
Units.SECOND.multiply(temporal.getTimeUnit().getValueInSeconds());
         } else {
@@ -446,7 +446,7 @@ final class VariableWrapper extends 
org.apache.sis.storage.netcdf.base.Variable
     @Override
     protected NumberRange<?> getRangeFallback() {
         if (variable instanceof EnhanceScaleMissingUnsigned) {
-            final EnhanceScaleMissingUnsigned ev = 
(EnhanceScaleMissingUnsigned) variable;
+            final var ev = (EnhanceScaleMissingUnsigned) variable;
             if (ev.hasValidData()) {
                 // Returns a MeasurementRange instance for signaling the 
caller that this is converted values.
                 return MeasurementRange.create(ev.getValidMin(), true, 
ev.getValidMax(), true, getUnit());
@@ -618,7 +618,7 @@ final class VariableWrapper extends 
org.apache.sis.storage.netcdf.base.Variable
             throws IOException, DataStoreException
     {
         if (variable instanceof CoordinateAxis1D) {
-            final CoordinateAxis1D axis = (CoordinateAxis1D) variable;
+            final var axis = (CoordinateAxis1D) variable;
             if (axis.isRegular()) {
                 final double start     = axis.getStart();
                 final double increment = axis.getIncrement();
diff --git 
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/measure/UnitAliases.properties
 
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/measure/UnitAliases.properties
index 48fd3cf3ed..4fde176ec2 100644
--- 
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/measure/UnitAliases.properties
+++ 
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/measure/UnitAliases.properties
@@ -1,8 +1,10 @@
 # Licensed to the Apache Software Foundation (ASF) under one or more 
contributor license agreements;
 # and to You under the Apache License, Version 2.0.
 
-# Contains only unit names not included in UnitNames.properties.
-# "degrees", "metres" and "meters" are handled as special cases.
+# Contains only unit names not included in the "UnitNames.properties" file.
+# Some aliases are the plural forms of units declared in their singular form
+# in "UnitNames.properties" file. Common units such as "degrees", "radians",
+# "seconds", "metres" and "meters" are handled as special cases in Java code.
 arcsec=\u2033
 days=d
 decibars=dbar
@@ -30,8 +32,6 @@ millibar=hPa
 millibars=hPa
 minutes=min
 percentage=%
-radians=rad
-seconds=s
 weeks=wk
 
 # Common misspellings
diff --git 
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/measure/UnitFormat.java 
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/measure/UnitFormat.java
index 08c892c1de..1c200704b6 100644
--- 
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/measure/UnitFormat.java
+++ 
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/measure/UnitFormat.java
@@ -17,7 +17,6 @@
 package org.apache.sis.measure;
 
 import java.util.Map;
-import java.util.List;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
@@ -555,15 +554,12 @@ public class UnitFormat extends Format implements 
javax.measure.format.UnitForma
             nameToUnit = map;
         }
         /*
-         * The `nameToUnit` map contains plural forms (declared in 
UnitAliases.properties),
-         * but we make a special case for "degrees", "metres" and "meters" 
because they
-         * appear in numerous places.
+         * The `nameToUnit` map contains plural forms (declared in 
"UnitAliases.properties" file),
+         * but we make a special case for common units such as "degrees", 
"radians", "seconds",
+         * "metres" and "meters" because they are repeated in units such as 
"kilometers".
          */
         uom = uom.replace('_', ' ').toLowerCase(locale);
-        uom = 
CharSequences.replace(CharSequences.replace(CharSequences.replace(CharSequences.toASCII(uom),
-                "meters",  "meter"),
-                "metres",  "metre"),
-                 DEGREES,  "degree").toString();
+        uom = removePlural(CharSequences.toASCII(uom));
         /*
          * Returns the unit with application of the power if it is part of the 
name.
          * For example, this method interprets "meter2" as "meter" raised to 
power 2.
@@ -589,16 +585,32 @@ appPow: if (unit == null) {
     /**
      * Copies all entries from the given "symbols to names" mapping to the 
given "names to units" mapping.
      * During this copy, keys are converted from symbols to names and values 
are converted from symbols to
-     * {@code Unit} instance. We use {@code Unit} values instead of their 
symbols because all {@code Unit}
+     * {@code Unit} instances. We use {@code Unit} values instead of their 
symbols because all {@code Unit}
      * instances are created at {@link Units} class initialization anyway (so 
we do not create new instance
-     * here), and it avoid to retain references to the {@link String} 
instances loaded by the resource bundle.
+     * here), and it avoids to retain references to the {@link String} 
instances loaded by the resource bundle.
      */
     private static void copy(final Locale locale, final ResourceBundle 
symbolToName, final Map<String,Unit<?>> nameToUnit) {
         for (final String symbol : symbolToName.keySet()) {
-            
nameToUnit.put(CharSequences.toASCII(symbolToName.getString(symbol).toLowerCase(locale)).toString().intern(),
 Units.get(symbol));
+            String name = 
CharSequences.toASCII(symbolToName.getString(symbol).toLowerCase(locale)).toString().intern();
+            nameToUnit.put(removePlural(name), Units.get(symbol));
         }
     }
 
+    /**
+     * Returns the given string with common units such as "degrees", 
"radians", "seconds", "metres" and "meters"
+     * replaced by their singular forms. All these units may have a prefix, 
for example as in "kilometres".
+     * The result may not be grammatically correct English, but those strings 
will not be visible to users.
+     * This is similar to making a string in lower cases before comparison in 
order to be case-insensitive.
+     */
+    private static String removePlural(CharSequence uom) {
+        uom = CharSequences.replace(uom,  DEGREES,  "degree");
+        uom = CharSequences.replace(uom, "radians", "radian");
+        uom = CharSequences.replace(uom, "seconds", "second");
+        uom = CharSequences.replace(uom, "meters",  "meter");
+        uom = CharSequences.replace(uom, "metres",  "metre");
+        return uom.toString();
+    }
+
     /**
      * Formats the specified unit.
      * This method performs the first of the following actions that can be 
done.
@@ -795,7 +807,7 @@ appPow: if (unit == null) {
             throws IOException
     {
         boolean isFirst = true;
-        final List<Map.Entry<?,? extends Number>> deferred = new 
ArrayList<>(components.size());
+        final var deferred = new ArrayList<Map.Entry<?,? extends 
Number>>(components.size());
         for (final Map.Entry<?,? extends Number> entry : 
components.entrySet()) {
             final Number power = entry.getValue();
             final int n = (power instanceof Fraction) ? ((Fraction) 
power).numerator : power.intValue();
@@ -1071,7 +1083,7 @@ appPow: if (unit == null) {
      */
     @Override
     public Unit<?> parse(final CharSequence symbols) throws 
MeasurementParseException {
-        final Position position = new Position();
+        final var position = new Position();
         Unit<?> unit = parse(symbols, position);
         final int length = symbols.length();
         int unrecognized;
@@ -1156,7 +1168,7 @@ appPow: if (unit == null) {
          *
          * The `start` variable is the index of the first character of the 
next unit term to parse.
          */
-        final Operation operation = new Operation(symbols);    // Enumeration 
value: NOOP, IMPLICIT, MULTIPLY, DIVIDE.
+        final var operation = new Operation(symbols);    // Enumeration value: 
NOOP, IMPLICIT, MULTIPLY, DIVIDE.
         Unit<?> unit = null;
         boolean hasSpaces = false;
         int i = start;
@@ -1240,7 +1252,7 @@ scan:   for (int n; i < end; i += n) {
                  */
                 case Style.OPEN: {
                     final int pos = i + Character.charCount(c);
-                    final ParsePosition sub = new ParsePosition(pos);
+                    final var sub = new ParsePosition(pos);
                     final Unit<?> term = parse(symbols, sub);
                     i = CharSequences.skipLeadingWhitespaces(symbols, 
sub.getIndex(), end);
                     if (i >= end || Character.codePointAt(symbols, i) != 
Style.CLOSE) {
@@ -1581,7 +1593,7 @@ search:     while ((i = 
CharSequences.skipTrailingWhitespaces(symbols, start, i)
                 return Double.parseDouble(term);                     // No 
exponent symbol and no superscript found.
             }
             // Example: "10⁻⁴". Split in base and exponent.
-            final StringBuilder buffer = new StringBuilder(s);
+            final var buffer = new StringBuilder(s);
             do {
                 buffer.appendCodePoint(Characters.toNormalScript(c));
                 if ((s -= Character.charCount(c)) <= 0) break;
diff --git 
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/measure/UnitNames_en_US.properties
 
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/measure/UnitNames_en_US.properties
index 94d76daee2..187486ff27 100644
--- 
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/measure/UnitNames_en_US.properties
+++ 
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/measure/UnitNames_en_US.properties
@@ -2,10 +2,13 @@
 # and to You under the Apache License, Version 2.0.
 cm=centimeter
 km=kilometer
+km\u2215h=kilometers per hour
 L=liter
 m=meter
 m\u00b2=square meter
 m\u00b3=cubic meter
+m\u2215s=meters per second
+m\u2215s\u00b2=meters per second squared
 mi=international mile
 mm=millimeter
 nm=nanometer
diff --git 
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Vocabulary.java
 
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Vocabulary.java
index 5cef3e30e1..e0f372470a 100644
--- 
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Vocabulary.java
+++ 
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Vocabulary.java
@@ -969,6 +969,11 @@ public class Vocabulary extends IndexedResourceBundle {
          */
         public static final short OriginalColors = 272;
 
+        /**
+         * Other
+         */
+        public static final short Other = 280;
+
         /**
          * Other surface
          */
diff --git 
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Vocabulary.properties
 
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Vocabulary.properties
index 14dc57b6fa..3ae9fe1411 100644
--- 
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Vocabulary.properties
+++ 
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Vocabulary.properties
@@ -198,6 +198,7 @@ Options                 = Options
 Origin                  = Origin
 OriginalColors          = Original colors
 OriginInCellCenter      = Origin in a cell center
+Other                   = Other
 Others                  = Others
 OtherSurface            = Other surface
 Page_1                  = Page {0}
diff --git 
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Vocabulary_fr.properties
 
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Vocabulary_fr.properties
index 8294ba244a..c1a58d477a 100644
--- 
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Vocabulary_fr.properties
+++ 
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Vocabulary_fr.properties
@@ -205,6 +205,7 @@ Options                 = Options
 Origin                  = Origine
 OriginalColors          = Couleurs originales
 OriginInCellCenter      = Origine au centre d\u2019une cellule
+Other                   = Autre
 Others                  = Autres
 OtherSurface            = Autre surface
 Page_1                  = Page {0}
diff --git 
a/endorsed/src/org.apache.sis.util/test/org/apache/sis/measure/UnitFormatTest.java
 
b/endorsed/src/org.apache.sis.util/test/org/apache/sis/measure/UnitFormatTest.java
index 12b52b6283..4aa647a8ba 100644
--- 
a/endorsed/src/org.apache.sis.util/test/org/apache/sis/measure/UnitFormatTest.java
+++ 
b/endorsed/src/org.apache.sis.util/test/org/apache/sis/measure/UnitFormatTest.java
@@ -58,7 +58,7 @@ public final class UnitFormatTest extends TestCase {
      */
     @Test
     public void verifyUnitConstants() {
-        final Set<String> declared = new HashSet<>(64);
+        final var declared = new HashSet<String>(64);
         for (final Field f : Units.class.getFields()) {
             if (Unit.class.isAssignableFrom(f.getType())) {
                 declared.add(f.getName());
@@ -182,7 +182,7 @@ public final class UnitFormatTest extends TestCase {
      */
     @Test
     public void testLabel() {
-        final UnitFormat f = new UnitFormat(Locale.ENGLISH);
+        final var f = new UnitFormat(Locale.ENGLISH);
         f.label(Units.METRE,  "mFoo");
         f.label(Units.SECOND, "sFoo");
         assertEquals("mFoo", f.format(Units.METRE));
@@ -212,7 +212,7 @@ public final class UnitFormatTest extends TestCase {
      */
     @Test
     public void testDuplicatedLabels() {
-        final UnitFormat f = new UnitFormat(Locale.ENGLISH);
+        final var f = new UnitFormat(Locale.ENGLISH);
         f.label(Units.DEGREE, "deg");
         f.label(Units.DEGREE, "dd");        // For "decimal degrees"
         roundtrip(f, "dd", "dd");
@@ -223,7 +223,7 @@ public final class UnitFormatTest extends TestCase {
      */
     @Test
     public void testFormatUCUM() {
-        final UnitFormat f = new UnitFormat(Locale.UK);
+        final var f = new UnitFormat(Locale.UK);
         f.setStyle(UnitFormat.Style.UCUM);
         assertEquals("m",   f.format(Units.METRE));
         assertEquals("km",  f.format(Units.KILOMETRE));
@@ -243,7 +243,7 @@ public final class UnitFormatTest extends TestCase {
      */
     @Test
     public void testFormatName() {
-        final UnitFormat f = new UnitFormat(Locale.UK);
+        final var f = new UnitFormat(Locale.UK);
         f.setStyle(UnitFormat.Style.NAME);
         assertEquals("metre",        f.format(Units.METRE));
         assertEquals("kilometre",    f.format(Units.KILOMETRE));
@@ -282,7 +282,7 @@ public final class UnitFormatTest extends TestCase {
      */
     @Test
     public void testFormatScaled() {
-        final UnitFormat f = new UnitFormat(Locale.UK);
+        final var f = new UnitFormat(Locale.UK);
         f.setStyle(UnitFormat.Style.SYMBOL);
         assertEquals("Mm",      f.format(Units.KILOMETRE .multiply(1000)));
         assertEquals("10⁵⋅m",   f.format(Units.KILOMETRE .multiply( 100)));
@@ -299,7 +299,7 @@ public final class UnitFormatTest extends TestCase {
      */
     @Test
     public void testFormatPower() {
-        final UnitFormat f = new UnitFormat(Locale.UK);
+        final var f = new UnitFormat(Locale.UK);
         f.setStyle(UnitFormat.Style.SYMBOL);
         assertEquals("m²",  f.format(Units.METRE     .pow(2)));
         assertEquals("cm²", f.format(Units.CENTIMETRE.pow(2)));
@@ -311,7 +311,7 @@ public final class UnitFormatTest extends TestCase {
      */
     @Test
     public void testFormatRatio() {
-        final UnitFormat f = new UnitFormat(Locale.UK);
+        final var f = new UnitFormat(Locale.UK);
         f.setStyle(UnitFormat.Style.SYMBOL);
         assertEquals( "m∕h", f.format(Units.METRE.divide(Units.HOUR)));
         assertEquals("mm∕h", f.format(Units.MILLIMETRE.divide(Units.HOUR)));
@@ -323,7 +323,7 @@ public final class UnitFormatTest extends TestCase {
      */
     @Test
     public void testFormatUnusual() {
-        final UnitFormat f = new UnitFormat(Locale.UK);
+        final var f = new UnitFormat(Locale.UK);
         final Unit<?> u1 = Units.SECOND.pow(-1).multiply(3);
         assertEquals("3∕s",        f.format(u1));
         assertEquals("3⋅m∕s",      f.format(Units.METRE.multiply(u1)));
@@ -338,7 +338,7 @@ public final class UnitFormatTest extends TestCase {
      */
     @Test
     public void testUnity() {
-        final UnitFormat f = new UnitFormat(Locale.UK);
+        final var f = new UnitFormat(Locale.UK);
         assertEquals(   "1∕m²", 
f.format(Units.UNITY.divide(Units.SQUARE_METRE)));
         assertEquals("10⁻²∕m²", 
f.format(Units.UNITY.divide(100).divide(Units.SQUARE_METRE)));
         assertEquals("%∕m²",    
f.format(Units.PERCENT.divide(Units.SQUARE_METRE)));
@@ -402,12 +402,22 @@ public final class UnitFormatTest extends TestCase {
         assertSame(Units.CUBIC_METRE, f.parse("mètre cube"));
     }
 
+    /**
+     * Tests parsing of names such "metres per second".
+     */
+    @Test
+    public void testParseNameWithRatio() {
+        final var f = new UnitFormat(Locale.UK);
+        assertSame(Units.METRES_PER_SECOND, f.parse("metres per second"));
+        assertSame(Units.METRES_PER_SECOND, f.parse("metres per seconds"));    
 // Mispelling sometime encoutered.
+    }
+
     /**
      * Tests parsing of names raised to some power, for example {@code 
"meter2"}.
      */
     @Test
     public void testParseNameRaisedToPower() {
-        final UnitFormat f = new UnitFormat(Locale.UK);
+        final var f = new UnitFormat(Locale.UK);
         assertSame(Units.SQUARE_METRE, f.parse("meter2"));
         assertSame(Units.HERTZ,        f.parse("second-1"));
     }
@@ -418,7 +428,7 @@ public final class UnitFormatTest extends TestCase {
      */
     @Test
     public void testParseEPSG() {
-        final UnitFormat f = new UnitFormat(Locale.UK);
+        final var f = new UnitFormat(Locale.UK);
         assertSame(Units.METRE,             f.parse("EPSG:9001"));
         assertSame(Units.METRE,             
f.parse("urn:ogc:def:uom:EPSG::9001"));
         assertSame(Units.METRES_PER_SECOND, 
f.parse("urn:ogc:def:uom:EPSG::1026"));
@@ -429,7 +439,7 @@ public final class UnitFormatTest extends TestCase {
      */
     @Test
     public void testParseURL() {
-        final UnitFormat f = new UnitFormat(Locale.UK);
+        final var f = new UnitFormat(Locale.UK);
         assertSame(Units.METRE, 
f.parse("http://www.opengis.net/def/uom/EPSG/0/9001";));
         assertSame(Units.DAY,   
f.parse("http://www.opengis.net/def/uom/UCUM/0/d";));
     }
@@ -439,7 +449,7 @@ public final class UnitFormatTest extends TestCase {
      */
     @Test
     public void testParseSymbol() {
-        final UnitFormat f = new UnitFormat(Locale.UK);
+        final var f = new UnitFormat(Locale.UK);
         assertSame(Units.METRE,         f.parse("m"));
         assertSame(Units.UNITY,         f.parse("m⁰"));
         assertSame(Units.METRE,         f.parse("m¹"));
@@ -461,7 +471,7 @@ public final class UnitFormatTest extends TestCase {
      */
     @Test
     public void testParsePrefix() {
-        final UnitFormat f = new UnitFormat(Locale.UK);
+        final var f = new UnitFormat(Locale.UK);
         ConventionalUnitTest.verify(Units.JOULE,       f.parse("kJ"),   "kJ",  
 1E+3);
         ConventionalUnitTest.verify(Units.HERTZ,       f.parse("MHz"),  "MHz", 
 1E+6);
         ConventionalUnitTest.verify(Units.PASCAL,      f.parse("daPa"), 
"daPa", 1E+1);
@@ -494,7 +504,7 @@ public final class UnitFormatTest extends TestCase {
      */
     @Test
     public void testParseTerms() {
-        final UnitFormat f = new UnitFormat(Locale.UK);
+        final var f = new UnitFormat(Locale.UK);
         assertSame(Units.SQUARE_METRE,      f.parse("m⋅m"));
         assertSame(Units.CUBIC_METRE,       f.parse("m⋅m⋅m"));
         assertSame(Units.CUBIC_METRE,       f.parse("m²⋅m"));
@@ -510,7 +520,7 @@ public final class UnitFormatTest extends TestCase {
      */
     @Test
     public void testParseTermsSeparatedBySpace() {
-        final UnitFormat f = new UnitFormat(Locale.UK);
+        final var f = new UnitFormat(Locale.UK);
         assertSame(Units.METRES_PER_SECOND, f.parse("m s**-1"));
         assertEqualsIgnoreSymbol(Units.KILOGRAM.divide(Units.SQUARE_METRE), 
f.parse("kg m**-2"));
 
@@ -525,7 +535,7 @@ public final class UnitFormatTest extends TestCase {
      */
     @Test
     public void testParseMultiplier() {
-        final UnitFormat f = new UnitFormat(Locale.UK);
+        final var f = new UnitFormat(Locale.UK);
         assertSame(Units.MILLIMETRE, f.parse("m/1000"));
         assertSame(Units.KILOMETRE,  f.parse( "1000*m"));
         assertSame(Units.KILOMETRE,  f.parse( "1000.0*m"));
@@ -548,7 +558,7 @@ public final class UnitFormatTest extends TestCase {
      */
     @Test
     public void testParseKilogram() {
-        final UnitFormat f = new UnitFormat(Locale.UK);
+        final var f = new UnitFormat(Locale.UK);
         /*
          * Kilograms should be identified even if they appear in an expression.
          * Current implementation creates a symbol early when it detects such 
case.
@@ -562,7 +572,7 @@ public final class UnitFormatTest extends TestCase {
      */
     @Test
     public void testParseInverseL() {
-        final UnitFormat f = new UnitFormat(Locale.UK);
+        final var f = new UnitFormat(Locale.UK);
         final Unit<?> u = f.parse("1/l");
         assertEquals("1∕L", u.toString());
     }
@@ -574,7 +584,7 @@ public final class UnitFormatTest extends TestCase {
      */
     @Test
     public void testParseExponentiation() {
-        final UnitFormat f = new UnitFormat(Locale.UK);
+        final var f = new UnitFormat(Locale.UK);
         assertSame(Units.HERTZ,             f.parse("s^-1"));
         assertSame(Units.HERTZ,             f.parse("s**-1"));
         assertSame(Units.METRES_PER_SECOND, f.parse("m*s^-1"));
@@ -586,7 +596,7 @@ public final class UnitFormatTest extends TestCase {
      */
     @Test
     public void testParseWithParenthesis() {
-        final UnitFormat f = new UnitFormat(Locale.UK);
+        final var f = new UnitFormat(Locale.UK);
         assertSame(Units.PASCAL, f.parse("kg∕(m⋅s²)"));
         assertSame(Units.PASCAL, f.parse("(kg)∕m∕s²"));
         assertSame(Units.VOLT,   f.parse("kg⋅m²∕(s³⋅A)"));
@@ -599,8 +609,8 @@ public final class UnitFormatTest extends TestCase {
      */
     @Test
     public void testParsePosition() {
-        final UnitFormat f = new UnitFormat(Locale.UK);
-        final ParsePosition pos = new ParsePosition(4);
+        final var f = new UnitFormat(Locale.UK);
+        final var pos = new ParsePosition(4);
         assertSame(Units.CENTIMETRE, f.parse("ABC cm foo", pos));
         assertEquals( 6, pos.getIndex(), "ParsePosition.getIndex()");
         assertEquals(-1, pos.getErrorIndex(), "ParsePosition.getErrorIndex()");
@@ -620,7 +630,7 @@ public final class UnitFormatTest extends TestCase {
      */
     @Test
     public void testClone() {
-        final UnitFormat f1 = new UnitFormat(Locale.FRANCE);
+        final var f1 = new UnitFormat(Locale.FRANCE);
         f1.label(Units.METRE,  "myMeterLabel");
         f1.label(Units.SECOND, "mySecondLabel");
         final UnitFormat f2 = f1.clone();
@@ -643,7 +653,7 @@ public final class UnitFormatTest extends TestCase {
      */
     @Test
     public void testParseAndFormat() {
-        final UnitFormat f = new UnitFormat(Locale.UK);
+        final var f = new UnitFormat(Locale.UK);
         roundtrip(f, "K.m2.kg-1.s-1",    "K⋅m²∕(kg⋅s)");
         roundtrip(f, "m.m6.m-3",         "m⋅m⁶∕m³");
         roundtrip(f, "Pa.s-1",           "Pa∕s");
@@ -713,7 +723,7 @@ public final class UnitFormatTest extends TestCase {
     public void testParseAndFormatLabel() {
         final Unit<Length> yard  = Units.METRE.multiply(0.9144);
         final Unit<?>      yard2 = yard.pow(2);
-        final UnitFormat f = new UnitFormat(Locale.ENGLISH);
+        final var f = new UnitFormat(Locale.ENGLISH);
         f.label(yard, "yd");
         roundtrip(f, "yd",    "yd",  yard);
         roundtrip(f, "yd**2", "yd²", yard2);
@@ -733,7 +743,7 @@ public final class UnitFormatTest extends TestCase {
      */
     @Test
     public void needForImprovements() {
-        final UnitFormat f = new UnitFormat(Locale.UK);
+        final var f = new UnitFormat(Locale.UK);
         roundtrip(f, "kg.kg-1.m.s-1",    "m∕s");
         roundtrip(f, "(m2.s.sr)-1",      "1∕(m²⋅s)");
         roundtrip(f, "m-2.s.rad-1",      "s∕m²");
diff --git a/netbeans-project/ivy.xml b/netbeans-project/ivy.xml
index 84d86ca69e..489f8cf876 100644
--- a/netbeans-project/ivy.xml
+++ b/netbeans-project/ivy.xml
@@ -23,7 +23,7 @@
         <dependency org="joda-time"              name="joda-time"              
 rev="2.10.3"/>
         <dependency org="com.google.guava"       name="guava"                  
 rev="30.1-jre"/>
         <dependency org="org.libreoffice"        name="libreoffice"            
 rev="24.8.4"/>
-        <dependency org="software.amazon.awssdk" name="s3"                     
 rev="2.31.68"/>
+        <dependency org="software.amazon.awssdk" name="s3"                     
 rev="2.33.4"/>
         <dependency org="org.antlr"              name="antlr4-maven-plugin"    
 rev="4.13.2"/>
         <dependency org="jakarta.servlet"        name="jakarta.servlet-api"    
 rev="6.1.0"/>
         <dependency org="org.osgi"               name="osgi.core"              
 rev="8.0.0"/>
diff --git 
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/metadata/MetadataSummary.java
 
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/metadata/MetadataSummary.java
index b63d30c961..b2f5931f8e 100644
--- 
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/metadata/MetadataSummary.java
+++ 
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/metadata/MetadataSummary.java
@@ -16,6 +16,7 @@
  */
 package org.apache.sis.gui.metadata;
 
+import java.util.Locale;
 import java.util.Collection;
 import java.util.StringJoiner;
 import javafx.application.Platform;
@@ -54,7 +55,7 @@ import org.opengis.util.ControlledVocabulary;
  *
  * @author  Smaniotto Enzo (GSoC)
  * @author  Martin Desruisseaux (Geomatys)
- * @version 1.3
+ * @version 1.5
  * @since   1.1
  */
 @DefaultProperty("metadata")
@@ -126,7 +127,7 @@ public class MetadataSummary extends Widget {
     @SuppressWarnings("this-escape")    // `this` appears in a cyclic graph.
     public MetadataSummary() {
         vocabulary  = Vocabulary.forLocale(null);
-        formats     = new VerboseFormats(vocabulary.getLocale());
+        formats     = new VerboseFormats(getLocale());
         information = new TitledPane[] {
             // If order is modified, revisit `getIdentificationInfo()`.
             new 
TitledPane(vocabulary.getString(Vocabulary.Keys.ResourceIdentification), new 
IdentificationInfo(this)),
@@ -303,7 +304,7 @@ public class MetadataSummary extends Widget {
     private static void applyChange(final ObservableValue<? extends Metadata> 
property,
                                     final Metadata oldValue, final Metadata 
metadata)
     {
-        final MetadataSummary s = (MetadataSummary) ((SimpleObjectProperty<?>) 
property).getBean();
+        final var s = (MetadataSummary) ((SimpleObjectProperty<?>) 
property).getBean();
         s.getter = null;                // In case this method is invoked 
before `Getter` completed.
         s.error  = null;
         if (metadata != oldValue) {
@@ -318,7 +319,7 @@ public class MetadataSummary extends Widget {
              */
             int i = 0;
             for (TitledPane pane : s.information) {
-                final Section<?> info = (Section<?>) pane.getContent();
+                final var info = (Section<?>) pane.getContent();
                 info.setInformation(metadata);
                 final boolean isEmpty   = info.isEmpty();
                 final boolean isPresent = (i < children.size()) && 
children.get(i) == pane;
@@ -364,6 +365,14 @@ public class MetadataSummary extends Widget {
      * Returns the given international string as a non-empty localized string, 
or {@code null} if none.
      */
     final String string(final InternationalString i18n) {
-        return (i18n != null) ? 
Strings.trimOrNull(i18n.toString(vocabulary.getLocale())) : null;
+        return (i18n != null) ? Strings.trimOrNull(i18n.toString(getLocale())) 
: null;
+    }
+
+    /**
+     * Returns the locale used by this widget for controls and messages.
+     */
+    @Override
+    public final Locale getLocale() {
+        return vocabulary.getLocale();
     }
 }
diff --git 
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/metadata/RepresentationInfo.java
 
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/metadata/RepresentationInfo.java
index 616df94d48..c286a36177 100644
--- 
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/metadata/RepresentationInfo.java
+++ 
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/metadata/RepresentationInfo.java
@@ -77,7 +77,7 @@ final class RepresentationInfo extends 
Section<SpatialRepresentation> {
         if (info instanceof GridSpatialRepresentation) {
             build((GridSpatialRepresentation) info);
         }
-        addLine(Vocabulary.Keys.ReferenceSystem, 
IdentifiedObjects.getDisplayName(referenceSystem, 
owner.vocabulary.getLocale()));
+        addLine(Vocabulary.Keys.ReferenceSystem, 
IdentifiedObjects.getDisplayName(referenceSystem, owner.getLocale()));
     }
 
     /**
@@ -89,19 +89,24 @@ final class RepresentationInfo extends 
Section<SpatialRepresentation> {
      */
     private void build(final GridSpatialRepresentation info) {
         addLine(Vocabulary.Keys.NumberOfDimensions, 
owner.format(info.getNumberOfDimensions()));
-        final StringBuffer gridSize   = new StringBuffer(20);
-        final StringBuffer resolution = new StringBuffer(20);
+        final var gridSize   = new StringBuffer(20);
+        final var resolution = new StringBuffer(20);
+        boolean hasName = false;
         for (final Dimension dim : nonNull(info.getAxisDimensionProperties())) 
{
-            final String  name = 
owner.string(Types.getCodeTitle(dim.getDimensionName()));
+            String name = 
owner.string(Types.getCodeTitle(dim.getDimensionName()));
             final Integer size = dim.getDimensionSize();
             if (name != null || size != null) {
                 if (gridSize.length() != 0) {
                     gridSize.append(" × ");
                 }
                 owner.format(size, gridSize);
+                if (hasName && name == null) {
+                    name = owner.vocabulary.getString(Vocabulary.Keys.Other);
+                }
                 if (name != null) {
                     if (size != null) gridSize.append(' ');
-                    gridSize.append(name);
+                    gridSize.append(name.toLowerCase(owner.getLocale()));
+                    hasName = true;
                 }
             }
             final Double r = dim.getResolution();
diff --git a/settings.gradle.kts b/settings.gradle.kts
index 0c19c8e84b..c173374243 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -68,7 +68,7 @@ dependencyResolutionManagement {
             library("esri.geometry", "com.esri.geometry",      
"esri-geometry-api")   .version {strictly("[2.0, 3.0[");  prefer("2.2.4")}
             library("libreoffice",   "org.libreoffice",        "libreoffice")  
       .version {strictly("[7.0, 8.0[");  prefer("24.8.4")}
             library("ucar",          "edu.ucar",               "cdm-core")     
       .version {strictly("[5.0, 6.0[");  prefer("5.5.3")}
-            library("aws.s3",        "software.amazon.awssdk", "s3")           
       .version {strictly("[2.0, 3.0[");  prefer("2.31.68")}
+            library("aws.s3",        "software.amazon.awssdk", "s3")           
       .version {strictly("[2.0, 3.0[");  prefer("2.33.4")}
         }
         create("tests") {
             library("geoapi",        "org.opengis",            
"geoapi-conformance")     .version {strictly(geoapiVersion)}


Reply via email to