sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1494567 - in /sis/branches/JDK7/core: sis-metadata/src/test/java/org/apache/sis/metadata/ sis-metadata/src/test/java/org/apache/sis/test/suite/ sis-utility/src/main/java/org/apache/sis/io/ sis-utility/src/main/java/org/apache/sis/util/coll...
Date Wed, 19 Jun 2013 11:45:06 GMT
Author: desruisseaux
Date: Wed Jun 19 11:45:06 2013
New Revision: 1494567

URL: http://svn.apache.org/r1494567
Log:
Safety guard against infinite recursivity in AbstractMetadata.toString().

Added:
    sis/branches/JDK7/core/sis-metadata/src/test/java/org/apache/sis/metadata/AbstractMetadataTest.java
  (with props)
Modified:
    sis/branches/JDK7/core/sis-metadata/src/test/java/org/apache/sis/metadata/MetadataStandardTest.java
    sis/branches/JDK7/core/sis-metadata/src/test/java/org/apache/sis/test/suite/MetadataTestSuite.java
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/io/IO.java
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/collection/TreeTableFormat.java
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages.java
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages.properties
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages_fr.properties
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.java
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.properties
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary_fr.properties

Added: sis/branches/JDK7/core/sis-metadata/src/test/java/org/apache/sis/metadata/AbstractMetadataTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-metadata/src/test/java/org/apache/sis/metadata/AbstractMetadataTest.java?rev=1494567&view=auto
==============================================================================
--- sis/branches/JDK7/core/sis-metadata/src/test/java/org/apache/sis/metadata/AbstractMetadataTest.java
(added)
+++ sis/branches/JDK7/core/sis-metadata/src/test/java/org/apache/sis/metadata/AbstractMetadataTest.java
[UTF-8] Wed Jun 19 11:45:06 2013
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.metadata;
+
+import org.apache.sis.test.DependsOn;
+import org.apache.sis.test.TestCase;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+import static org.apache.sis.test.TestUtilities.toTreeStructure;
+
+
+/**
+ * Tests the {@link AbstractMetadata} class.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @since   0.3 (derived from geotk-2.4)
+ * @version 0.3
+ * @module
+ */
+@DependsOn(MetadataStandardTest.class)
+public final strictfp class AbstractMetadataTest extends TestCase {
+    /**
+     * Tests the {@link AbstractMetadata#hashCode()} method on an object having cyclic associations.
+     * This is the same test than {@link MetadataStandardTest#testHashCodeOnCyclicMetadata()},
with
+     * only a different entry point.
+     *
+     * @see MetadataStandardTest#testHashCodeOnCyclicMetadata()
+     */
+    @Test
+    public void testHashCodeOnCyclicMetadata() {
+        final int code = MetadataStandardTest.createCyclicMetadata().hashCode();
+        assertEquals(code, MetadataStandardTest.createCyclicMetadata().hashCode());
+    }
+
+    /**
+     * Tests the {@link AbstractMetadata#toString()} method on an object having cyclic associations.
+     * In absence of safety guard against infinite recursivity, this test would produce either
a
+     * {@link StackOverflowError} or an {@link OutOfMemoryError} (after quite a long time).
+     *
+     * <p>The tree formatted by this test is:</p>
+     * {@preformat text
+     *     DefaultPlatform
+     *       ├─Description……………………… A platform.
+     *       └─Instrument
+     *           ├─Type……………………………… An instrument type.
+     *           └─Mounted on
+     *             (cycle omitted)
+     * }
+     */
+    @Test
+    public void testToStringOnCyclicMetadata() {
+        final String text = MetadataStandardTest.createCyclicMetadata().toString();
+        /*
+         * We can not perform a full comparison of the string, since it is locale-dependent.
+         * Compare only the tree structure. The full tree is English is shown in javadoc.
+         */
+        assertTrue(text, text.startsWith("DefaultPlatform"));
+        assertArrayEquals(new String[] {
+            "",
+            "  ├─",
+            "  └─",
+            "      ├─",
+            "      └─",
+            "        (",
+            ""}, toTreeStructure(text));
+    }
+}

Propchange: sis/branches/JDK7/core/sis-metadata/src/test/java/org/apache/sis/metadata/AbstractMetadataTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sis/branches/JDK7/core/sis-metadata/src/test/java/org/apache/sis/metadata/AbstractMetadataTest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain;charset=UTF-8

Modified: sis/branches/JDK7/core/sis-metadata/src/test/java/org/apache/sis/metadata/MetadataStandardTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-metadata/src/test/java/org/apache/sis/metadata/MetadataStandardTest.java?rev=1494567&r1=1494566&r2=1494567&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-metadata/src/test/java/org/apache/sis/metadata/MetadataStandardTest.java
[UTF-8] (original)
+++ sis/branches/JDK7/core/sis-metadata/src/test/java/org/apache/sis/metadata/MetadataStandardTest.java
[UTF-8] Wed Jun 19 11:45:06 2013
@@ -201,16 +201,19 @@ public final strictfp class MetadataStan
     /**
      * Tests the {@link MetadataStandard#hashCode(Object)} method on an object having cyclic
associations.
      * In absence of safety guard against infinite recursivity, this test would produce {@link
StackOverflowError}.
+     *
+     * @see AbstractMetadataTest#testHashCodeOnCyclicMetadata()
      */
     @Test
     @DependsOnMethod("testHashCode")
     public void testHashCodeOnCyclicMetadata() {
-        final int code = createCyclicMetadata().hashCode();
+        final MetadataStandard std = MetadataStandard.ISO_19115;
+        final int code = std.hashCode(createCyclicMetadata());
         /*
          * Following line checks that the hash code is stable, just for doing something with
the code.
          * The real test was actually to ensure that the above line didn't threw a StackOverflowError.
          */
-        assertEquals(code, createCyclicMetadata().hashCode());
+        assertEquals(code, std.hashCode(createCyclicMetadata()));
     }
 
     /**

Modified: sis/branches/JDK7/core/sis-metadata/src/test/java/org/apache/sis/test/suite/MetadataTestSuite.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-metadata/src/test/java/org/apache/sis/test/suite/MetadataTestSuite.java?rev=1494567&r1=1494566&r2=1494567&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-metadata/src/test/java/org/apache/sis/test/suite/MetadataTestSuite.java
[UTF-8] (original)
+++ sis/branches/JDK7/core/sis-metadata/src/test/java/org/apache/sis/test/suite/MetadataTestSuite.java
[UTF-8] Wed Jun 19 11:45:06 2013
@@ -51,6 +51,7 @@ import org.junit.BeforeClass;
     org.apache.sis.metadata.TreeTableViewTest.class,
     org.apache.sis.metadata.MetadataStandardTest.class,
     org.apache.sis.metadata.PrunerTest.class,
+    org.apache.sis.metadata.AbstractMetadataTest.class,
     org.apache.sis.metadata.iso.AllMetadataTest.class
 })
 public final strictfp class MetadataTestSuite extends TestSuite {

Modified: sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/io/IO.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/io/IO.java?rev=1494567&r1=1494566&r2=1494567&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/io/IO.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/io/IO.java [UTF-8] Wed
Jun 19 11:45:06 2013
@@ -23,7 +23,7 @@ import java.io.Writer;
 import java.io.StringWriter;
 import java.io.CharArrayWriter;
 import org.apache.sis.util.Static;
-import org.apache.sis.util.resources.Messages;
+import org.apache.sis.util.resources.Vocabulary;
 
 
 /**
@@ -143,7 +143,7 @@ public final class IO extends Static {
         if (content != null) {
             return content.toString();
         }
-        return Messages.format(Messages.Keys.UnavailableContent);
+        return Vocabulary.format(Vocabulary.Keys.UnavailableContent);
     }
 
     /**

Modified: sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/collection/TreeTableFormat.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/collection/TreeTableFormat.java?rev=1494567&r1=1494566&r2=1494567&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/collection/TreeTableFormat.java
[UTF-8] (original)
+++ sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/collection/TreeTableFormat.java
[UTF-8] Wed Jun 19 11:45:06 2013
@@ -17,6 +17,7 @@
 package org.apache.sis.util.collection;
 
 import java.util.Arrays;
+import java.util.IdentityHashMap;
 import java.util.Iterator;
 import java.util.Map;
 import java.util.List;
@@ -38,6 +39,7 @@ import org.apache.sis.util.Workaround;
 import org.apache.sis.util.CharSequences;
 import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.util.resources.Errors;
+import org.apache.sis.util.resources.Vocabulary;
 import org.apache.sis.internal.util.LocalizedParseException;
 
 import static org.apache.sis.util.Characters.NO_BREAK_SPACE;
@@ -79,6 +81,16 @@ import static org.apache.sis.util.Charac
  * then insert the {@code "……"} string, repeat the {@code '…'} character as many time
as needed
  * (may be zero), and finally insert a space</cite>".
  *
+ * {@section Safety against infinite recursivity}
+ * Some {@code TreeTable} implementations generate the nodes dynamically as wrappers around
Java objects.
+ * Such Java objects may contain cyclic associations (<var>A</var> contains <var>B</var>
contains <var>C</var>
+ * contains <var>A</var>), which result in a tree of infinite depth. Some examples
can been found in ISO 19115
+ * metadata. This {@code TreeTableFormat} class contains a safety against such cycles. The
algorithm is based
+ * on the assumption that for each node, the values and children are fully determined by
the
+ * {@linkplain TreeTable.Node#getUserObject() user object}, if non-null. Consequently for
each node <var>C</var>
+ * to be formatted, if the user object of that node is the same instance (in the sense of
the {@code ==} operator)
+ * than the user object of a parent node <var>A</var>, then the children of the
<var>C</var> node will not be formatted.
+ *
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @since   0.3 (derived from geotk-2.0)
  * @version 0.3
@@ -142,6 +154,12 @@ public class TreeTableFormat extends Tab
     private transient String treeBlank, treeLine, treeCross, treeEnd;
 
     /**
+     * The map to be given to {@link Writer#parentObjects}, created when first needed
+     * and reused for subsequent formating.
+     */
+    private transient Map<Object,Object> parentObjects;
+
+    /**
      * Creates a new tree table format.
      *
      * @param locale   The locale to use for numbers, dates and angles formatting,
@@ -552,14 +570,33 @@ public class TreeTableFormat extends Tab
         private boolean[] isLast;
 
         /**
+         * The {@linkplain TreeTable.Node#getUserObject() user object} of the parent nodes.
+         * We use this map as a safety against infinite recursivity, on the assumption that
+         * the node content and children are fully determined by the user object.
+         *
+         * <p>User objects in this map will be compared by the identity comparator
rather than by the
+         * {@code equals(Object)} method because the later may be costly and could itself
be vulnerable
+         * to infinite recursivity if it has not been implemented defensively.</p>
+         *
+         * <p>We check the user object instead than the node itself because the same
node instance can
+         * theoretically not appear twice with a different parent.</p>
+         */
+        private final Map<Object,Object> parentObjects;
+
+        /**
          * Creates a new instance which will write in the given appendable.
+         *
+         * @param out           Where to format the tree.
+         * @param column        The columns of the tree table to format.
+         * @param parentObjects An initially empty {@link IdentityHashMap}.
          */
-        Writer(final Appendable out, final TableColumn<?>[] columns) {
+        Writer(final Appendable out, final TableColumn<?>[] columns, final Map<Object,Object>
parentObjects) {
             super(columns.length >= 2 ? new TableAppender(out, "") : out);
             this.columns = columns;
             this.formats = getFormats(columns, false);
             this.values  = new Object[columns.length];
             this.isLast  = new boolean[8];
+            this.parentObjects = parentObjects;
             setTabulationExpanded(true);
             setLineSeparator(" ¶ ");
         }
@@ -631,13 +668,38 @@ public class TreeTableFormat extends Tab
             if (level >= isLast.length) {
                 isLast = Arrays.copyOf(isLast, level*2);
             }
-            final Iterator<? extends TreeTable.Node> it = node.getChildren().iterator();
-            boolean hasNext = it.hasNext();
-            while (hasNext) {
-                final TreeTable.Node child = it.next();
-                hasNext = it.hasNext();
-                isLast[level] = !hasNext; // Must be set before the call to 'format' below.
-                format(child, level+1);
+            /*
+             * Format the children only if we do not detect an infinite recursivity. Our
recursivity detection
+             * algorithm assumes that the node content is fully determined by the user object.
If that assumption
+             * holds, then we have an infinite recursivity if the user object of the current
node is also the user
+             * object of a parent node.
+             *
+             * Note that the value stored in the 'parentObjects' map needs to be the 'userObject'
because we want
+             * the map value to be null if the user object is null, in order to format the
children even if many
+             * null user objects exist in the tree.
+             */
+            final Object userObject = node.getUserObject();
+            if (parentObjects.put(userObject, userObject) == null) {
+                final Iterator<? extends TreeTable.Node> it = node.getChildren().iterator();
+                boolean hasNext = it.hasNext();
+                while (hasNext) {
+                    final TreeTable.Node child = it.next();
+                    hasNext = it.hasNext();
+                    isLast[level] = !hasNext; // Must be set before the call to 'format'
below.
+                    format(child, level+1);
+                }
+                parentObjects.remove(userObject);
+            } else {
+                /*
+                 * Detected a recursivity. Format "(cycle omitted)" just below the node.
+                 */
+                for (int i=0; i<level; i++) {
+                    out.append(getTreeSymbols(true, isLast[i]));
+                }
+                final Locale locale = getLocale();
+                out.append('(').append(Vocabulary.getResources(locale)
+                   .getString(Vocabulary.Keys.CycleOmitted).toLowerCase(locale))
+                   .append(')').append(lineSeparator);
             }
         }
     }
@@ -668,8 +730,15 @@ public class TreeTableFormat extends Tab
             final List<TableColumn<?>> c = tree.getColumns();
             columns = c.toArray(new TableColumn<?>[c.size()]);
         }
-        final Writer out = new Writer(toAppendTo, columns);
-        out.format(tree.getRoot(), 0);
-        out.flush();
+        if (parentObjects == null) {
+            parentObjects = new IdentityHashMap<>();
+        }
+        try {
+            final Writer out = new Writer(toAppendTo, columns, parentObjects);
+            out.format(tree.getRoot(), 0);
+            out.flush();
+        } finally {
+            parentObjects.clear();
+        }
     }
 }

Modified: sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages.java?rev=1494567&r1=1494566&r2=1494567&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages.java
[UTF-8] (original)
+++ sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages.java
[UTF-8] Wed Jun 19 11:45:06 2013
@@ -63,7 +63,7 @@ public final class Messages extends Inde
          * Property “{0}” has been discarded in favor of “{1}”, because those two
properties are
          * mutually exclusive.
          */
-        public static final int DiscardedExclusiveProperty_2 = 4;
+        public static final int DiscardedExclusiveProperty_2 = 1;
 
         /**
          * Text were discarded for some locales.
@@ -74,11 +74,6 @@ public final class Messages extends Inde
          * Property “{0}” is hidden by “{1}”.
          */
         public static final int PropertyHiddenBy_2 = 3;
-
-        /**
-         * Unavailable content.
-         */
-        public static final int UnavailableContent = 1;
     }
 
     /**

Modified: sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages.properties
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages.properties?rev=1494567&r1=1494566&r2=1494567&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages.properties
[ISO-8859-1] (original)
+++ sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages.properties
[ISO-8859-1] Wed Jun 19 11:45:06 2013
@@ -18,4 +18,3 @@ ChangedContainerCapacity_2      = Change
 DiscardedExclusiveProperty_2    = Property \u201c{0}\u201d has been discarded in favor of
\u201c{1}\u201d, because those two properties are mutually exclusive.
 PropertyHiddenBy_2              = Property \u201c{0}\u201d is hidden by \u201c{1}\u201d.
 LocalesDiscarded                = Text were discarded for some locales.
-UnavailableContent              = Unavailable content.

Modified: sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages_fr.properties
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages_fr.properties?rev=1494567&r1=1494566&r2=1494567&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages_fr.properties
[ISO-8859-1] (original)
+++ sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Messages_fr.properties
[ISO-8859-1] Wed Jun 19 11:45:06 2013
@@ -18,4 +18,3 @@ ChangedContainerCapacity_2      = Change
 DiscardedExclusiveProperty_2    = La propri\u00e9t\u00e9 \u201c{0}\u201d a \u00e9t\u00e9
\u00e9cart\u00e9e en faveur de \u201c{1}\u201d, parce que ces deux propri\u00e9t\u00e9s sont
mutuellement exclusives.
 PropertyHiddenBy_2              = La propri\u00e9t\u00e9 \u201c{0}\u201d est masqu\u00e9e
par \u201c{1}\u201d.
 LocalesDiscarded                = Des textes ont \u00e9t\u00e9 ignor\u00e9s pour certaines
langues.
-UnavailableContent              = Contenu non-disponible.

Modified: sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.java?rev=1494567&r1=1494566&r2=1494567&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.java
[UTF-8] (original)
+++ sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.java
[UTF-8] Wed Jun 19 11:45:06 2013
@@ -110,6 +110,11 @@ public final class Vocabulary extends In
         public static final int CurrentDirectory = 33;
 
         /**
+         * Cycle omitted
+         */
+        public static final int CycleOmitted = 54;
+
+        /**
          * Daylight time
          */
         public static final int DaylightTime = 24;
@@ -290,6 +295,11 @@ public final class Vocabulary extends In
         public static final int Type = 1;
 
         /**
+         * Unavailable content.
+         */
+        public static final int UnavailableContent = 53;
+
+        /**
          * Untitled
          */
         public static final int Untitled = 37;

Modified: sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.properties
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.properties?rev=1494567&r1=1494566&r2=1494567&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.properties
[ISO-8859-1] (original)
+++ sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.properties
[ISO-8859-1] Wed Jun 19 11:45:06 2013
@@ -25,6 +25,7 @@ Code_1             = {0} code
 Commands           = Commands
 CurrentDateTime    = Current date and time
 CurrentDirectory   = Current directory
+CycleOmitted       = Cycle omitted
 DaylightTime       = Daylight time
 Destination        = Destination
 Dimensions         = Dimensions
@@ -62,6 +63,7 @@ TemporaryFiles     = Temporary files
 Timezone           = Timezone
 Type               = Type
 Untitled           = Untitled
+UnavailableContent = Unavailable content.
 UserHome           = User home directory
 Value              = Value
 Variables          = Variables

Modified: sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary_fr.properties
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary_fr.properties?rev=1494567&r1=1494566&r2=1494567&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary_fr.properties
[ISO-8859-1] (original)
+++ sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary_fr.properties
[ISO-8859-1] Wed Jun 19 11:45:06 2013
@@ -25,6 +25,7 @@ Code_1             = Code {0}
 Commands           = Commandes
 CurrentDateTime    = Date et heure courantes
 CurrentDirectory   = R\u00e9pertoire courant
+CycleOmitted       = Cycle omit
 DaylightTime       = Heure normale
 Destination        = Destination
 Dimensions         = Dimensions
@@ -62,6 +63,7 @@ TemporaryFiles     = Fichiers temporaire
 Timezone           = Fuseau horaire
 Type               = Type
 Untitled           = Sans titre
+UnavailableContent = Contenu non-disponible.
 UserHome           = R\u00e9pertoire de l'utilisateur
 Value              = Valeur
 Variables          = Variables



Mime
View raw message