Repository: WeblateOrg/weblate

Issue:
Create component using excel ，state is not empty
### Describe the issue

I have some translation entries where target is empty and fuzzy is true. 
When I use them to create components, weblate shows that they are [Need edit] and the translation is empty. 
How should I filter such entries? 
The expected translation status should be empty

### I already tried

- [X] I've read and searched [the documentation](https://docs.weblate.org/).
- [X] I've searched for similar filed issues in this repository.

### Steps to reproduce the behavior

Create component using excel 

### Expected behavior

_No response_

### Screenshots

![image](https://github.com/WeblateOrg/weblate/assets/14290268/fa55e33c-9510-43d3-a970-35683710340e)


### Exception traceback

_No response_

### How do you run Weblate?

Docker container

### Weblate versions

5.3.1

### Weblate deploy checks

_No response_

### Additional context

_No response_


Discussion:

Resolving patch:
diff --git a/weblate/formats/base.py b/weblate/formats/base.py
--- a/weblate/formats/base.py
+++ b/weblate/formats/base.py
@@ -222,9 +222,13 @@ def id_hash(self) -> int:
             self.context,
         )
 
-    def is_translated(self):
+    def has_translation(self) -> bool:
+        """Check whether unit has translation."""
+        return any(split_plural(self.target))
+
+    def is_translated(self) -> bool:
         """Check whether unit is translated."""
-        return bool(self.target)
+        return self.has_translation()
 
     def is_approved(self, fallback=False) -> bool:
         """Check whether unit is approved."""
diff --git a/weblate/formats/convert.py b/weblate/formats/convert.py
--- a/weblate/formats/convert.py
+++ b/weblate/formats/convert.py
@@ -60,8 +60,8 @@ class ConvertPoUnit(PoUnit):
     def is_translated(self):
         """Check whether unit is translated."""
         if self.parent.is_template:
-            return bool(self.target)
-        return self.unit is not None and bool(self.target)
+            return self.has_translation()
+        return self.unit is not None and self.has_translation()
 
     def is_fuzzy(self, fallback=False):
         """Check whether unit needs editing."""
@@ -91,7 +91,7 @@ def is_approved(self, fallback=False):
     def is_translated(self):
         """Check whether unit is translated."""
         if self.parent.is_template:
-            return bool(self.target)
+            return self.has_translation()
         return self.unit is not None
 
     @cached_property
diff --git a/weblate/formats/ttkit.py b/weblate/formats/ttkit.py
--- a/weblate/formats/ttkit.py
+++ b/weblate/formats/ttkit.py
@@ -132,7 +132,7 @@ def is_fuzzy(self, fallback=False):
         # Most of the formats do not support this, but they
         # happily return False
         if isinstance(self.unit, SUPPORTS_FUZZY):
-            return self.unit.isfuzzy()
+            return self.has_translation() and self.unit.isfuzzy()
         return fallback
 
     def has_content(self) -> bool:
@@ -628,14 +628,14 @@ def get_xliff_units(self):
     def get_xliff_nodes(self):
         return (self.get_unit_node(unit) for unit in self.get_xliff_units())
 
-    def get_xliff_states(self):
-        result = []
+    def get_xliff_states(self) -> set[str]:
+        result = set()
         for node in self.get_xliff_nodes():
             if node is None:
                 continue
             state = node.get("state", None)
             if state is not None:
-                result.append(state)
+                result.add(state)
         return result
 
     @cached_property
@@ -658,9 +658,9 @@ def is_translated(self):
         We replace Translate Toolkit logic here as the isfuzzy is pretty much wrong
         there, see is_fuzzy docs.
         """
-        return bool(self.target)
+        return self.has_translation()
 
-    def is_fuzzy(self, fallback=False):
+    def is_fuzzy(self, fallback: bool = False) -> bool:
         """
         Check whether unit needs edit.
 
@@ -669,8 +669,8 @@ def is_fuzzy(self, fallback=False):
 
         That's why we handle it on our own.
         """
-        return self.target and any(
-            state in XLIFF_FUZZY_STATES for state in self.get_xliff_states()
+        return self.has_translation() and XLIFF_FUZZY_STATES.intersection(
+            self.get_xliff_states()
         )
 
     def set_state(self, state) -> None:
@@ -1735,7 +1735,7 @@ def target(self):
 
     def is_translated(self):
         """Check whether unit is translated."""
-        return bool(self.target)
+        return self.has_translation()
 
 
 class SubRipFormat(TTKitFormat):


Test patch:
diff --git a/weblate/trans/tests/test_files.py b/weblate/trans/tests/test_files.py
--- a/weblate/trans/tests/test_files.py
+++ b/weblate/trans/tests/test_files.py
@@ -159,15 +159,11 @@ def test_import_suggest(self) -> None:
         self.assertEqual(translation.stats.translated, 0)
         self.assertEqual(translation.stats.fuzzy, 0)
         self.assertEqual(translation.stats.all, 4)
-        self.assertEqual(
-            translation.stats.suggestions, 2 if self.test_file == TEST_XLIFF else 1
-        )
+        self.assertEqual(translation.stats.suggestions, 1)
 
     def test_import_xliff(self) -> None:
         response = self.do_import(test_file=TEST_XLIFF, follow=True)
-        self.assertContains(
-            response, "updated: 2" if self.has_plurals else "updated: 1"
-        )
+        self.assertContains(response, "updated: 1")
         # Verify stats
         translation = self.get_translation()
         self.assertEqual(translation.stats.translated, 1)