Diff for "Translations/Specs/UpstreamImportIntoUbuntu/FixingIsImported/setCurrentTranslation"

Not logged in - Log In / Register

Differences between revisions 5 and 36 (spanning 31 versions)
Revision 5 as of 2010-03-25 22:54:28
Size: 2743
Editor: jtv
Comment:
Revision 36 as of 2010-06-19 03:51:36
Size: 6051
Editor: jtv
Comment:
Deletions are marked like this. Additions are marked like this.
Line 9: Line 9:
Messages have been validated against gettext (otherwise you wouldn't be setting them as current).
Line 12: Line 14:
When we look for an "identical" message, we look for ones that are either
shared or diverged in the same template that we're looking at. We
When we look for an "identical" message, we look for one that is either
shared, or diverged in the same template that we're looking at. We
Line 15: Line 17:

== Guiding principles ==

There are two ''sides'' to translation: the Ubuntu side and the upstream side. A POFile is always either on the one side or on the other, though it can share translations with the other side. Each side can have its own shared translations, and each POFile can have its own diverged translations.

For a given POTMsgSet in a given POFile, its relationship with the other translation side can be in one of three states:
 1. '''Diverged''': the current translation in the POFile is diverged from the shared translation for the POFile's own side. New translations should stay diverged, unless they match existing shared translations (in which case the translation converges with the matching existing translation). So `setCurrentTranslation` may end or maintain a divergence, but never introduce a new one. It may however create a diverged clone of an existing translation message in order to maintain a divergence.
 1. '''Shared''': the current translation is shared with other POFiles on the POFile's own side—but not with the other side. New translations should stay shared on the POFile's own side, but only converge with those on the other side if the new translation is identical to that side's shared translation. So `setCurrentTranslation` may keep the translation shared, or bring it into the "tracking" state described below.
 1. '''Tracking''': the POFile's shared translation is also the other side's shared translation (including the case where neither side has a shared translation). The other side may still have diverged messages, as may other POFiles on the POFile's own side, but those are not relevant here. The "merging policy" determines whether a new translation should also be shared on the other side. So `setCurrentTranslation` may break the tracking or maintain it, but never cause divergence.

'''(NEW/CHANGED)''' Exception: In the shared state, if the other side has no shared translation and the merging policy allows it, `setCurrentTranslation` steals the other side's flag (and thus moves the message to the tracking state).
Line 19: Line 33:

  If there is already an identical shared message:
{{{
  If there is already a shared message identical to current:
Line 25: Line 39:
}}}
Line 27: Line 42:
{{{
  current.is_current = False
}}}
Line 28: Line 46:
  current.is_current = False Z: Do nothing. There is no incumbent message.
Line 32: Line 51:
1. create TM 'new'
   new.is_current = True
Some numbers are unused because their scenarios have collapsed into other ones.
Line 35: Line 53:
2. create TM 'new'
   new.is_current = True
   new.potemplate = current.potemplate
1. Create & activate.
{{{
create TM 'new'
new.is_current = True
}}}
Line 39: Line 59:
4. new.is_current = True 2. Create, diverge, activate.
{{{
create TM 'new'
new.is_current = True
new.potemplate = current.potemplate
}}}
Line 41: Line 66:
5. if new.is_current: pass
     else: (2)
4. Activate.
{{{
new.is_current = True
}}}
Line 44: Line 71:
7. new.potemplate = None (watch for existing identical TM)
   new.is_current = True
5. '''(NEW/CHANGED)''' If other is not current, it's a suggestion. Diverge & activate. (If it is current, deactivating the old diverged current message has already unmasked it).
{{{
if not new.is_current: (2)
}}}
Line 47: Line 76:
⊕. MERGING POLICY determines if we need to do:
   Look for shared translation with the is_other flag set: 'other'
   If found:
       other.is_other = False
       new.is_other = True
6. '''(NEW/CHANGED)''' If other is not already current, fork a diverged message. (If it is current, deactivating the old diverged current message has already unmasked it).
{{{
if not new.is_current:
    new.potemplate = current.potemplate
    new.is_current = True
}}}

7. Converge & activate.
{{{
new.potemplate = None # (watch for existing identical TM)
new.is_current = True
}}}

== Capture the Flag ==

Look for a shared translation with the `is_other` flag set: '`other`'.

*. If the merging policy says so and the other side is untranslated, assume the other flag as well:
{{{
    if other is None:
        new.is_other = True
}}}

⊕. Tracking. If the merging policy says so, steal the other flag:
{{{
    other.is_other = False
    new.is_other = True
}}}
Line 59: Line 111:
{{{
                +-------------------------------------+
                | IDENTICAL EXISTING TM 'new' |
                +------+--------+----------+----------+
                | | | | upstream |
                | None | shared | diverged | shared |
 +---+----------+---------------+----------+----------+
 | C | None | Z1⊕ | Z4⊕ | Z7⊕ | Z4⊕ |
 | U +----------+------+--------+----------+----------+
 | R | shared | B1 | B4 | B7 | B4 |
 | R +----------+------+--------+----------+----------+
 | E | diverged | A2 | A5 | A4 | A5 |
 | N +----------+------+--------+----------+----------+
 | T | upstream | B1⊕ | B4⊕ | B7⊕ | ∅ |
 | | shared | | | | |
 +---+----------+------+--------+----------+----------+
}}}
Parenthesized elements are no-ops in their specific situations.

||<|2-2#E0E0E0> ||<-6:> IDENTICAL EXISTING TM 'new' ||
|| None || shared || diverged || upstream shared ||
||<|4>CURRENT || None || Z1* || Z4* || Z7* || Z4(*) ||
|| shared || B1* || B4* || B7* || B4(*) ||
|| diverged || A2 || A5 || A4 || A6 ||
|| upstream shared || B1⊕ || B4⊕ || B7⊕ || (B4⊕) ||
Line 85: Line 128:


== Implementation notes ==

See [[https://code.launchpad.net/~jtv/launchpad/recife-552639/+merge/24883|lp:~jtv/launchpad/recife-552639]]

This implements two methods: one for setting the upstream translation, and one for setting the Ubuntu translation. An upstream translation also overrides Ubuntu translations; whether the converse also happens when translating in Ubuntu is determined by an optional argument.

The code calls the "current" message the "incumbent," and the "existing" message the "twin."

If the merging policy approves, the newly activated instruction will also receive the "other flag" if there is no current translation to steal it from.

Setting a translation

Assumptions

We're not setting a translation that's identical to the current one.

We've checked that lock_timestamp is newer than the last update date.

Messages have been validated against gettext (otherwise you wouldn't be setting them as current).

A diverged message cannot be both the current Ubuntu message and the current upstream message. Those would be diverged in different templates.

When we look for an "identical" message, we look for one that is either shared, or diverged in the same template that we're looking at. We completely ignore messages that are diverged to other templates.

Guiding principles

There are two sides to translation: the Ubuntu side and the upstream side. A POFile is always either on the one side or on the other, though it can share translations with the other side. Each side can have its own shared translations, and each POFile can have its own diverged translations.

For a given POTMsgSet in a given POFile, its relationship with the other translation side can be in one of three states:

  1. Diverged: the current translation in the POFile is diverged from the shared translation for the POFile's own side. New translations should stay diverged, unless they match existing shared translations (in which case the translation converges with the matching existing translation). So setCurrentTranslation may end or maintain a divergence, but never introduce a new one. It may however create a diverged clone of an existing translation message in order to maintain a divergence.

  2. Shared: the current translation is shared with other POFiles on the POFile's own side—but not with the other side. New translations should stay shared on the POFile's own side, but only converge with those on the other side if the new translation is identical to that side's shared translation. So setCurrentTranslation may keep the translation shared, or bring it into the "tracking" state described below.

  3. Tracking: the POFile's shared translation is also the other side's shared translation (including the case where neither side has a shared translation). The other side may still have diverged messages, as may other POFiles on the POFile's own side, but those are not relevant here. The "merging policy" determines whether a new translation should also be shared on the other side. So setCurrentTranslation may break the tracking or maintain it, but never cause divergence.

(NEW/CHANGED) Exception: In the shared state, if the other side has no shared translation and the merging policy allows it, setCurrentTranslation steals the other side's flag (and thus moves the message to the tracking state).

What happens to the existing current message

A: Deactivate & converge.

  If there is already a shared message identical to current:
    current.delete()
  else:
    current.is_current = False
    current.potemplate = None

B: Deactivate.

  current.is_current = False

Z: Do nothing. There is no incumbent message.

What happens to the new current message

Some numbers are unused because their scenarios have collapsed into other ones.

1. Create & activate.

create TM 'new'
new.is_current = True

2. Create, diverge, activate.

create TM 'new'
new.is_current = True
new.potemplate = current.potemplate

4. Activate.

new.is_current = True

5. (NEW/CHANGED) If other is not current, it's a suggestion. Diverge & activate. (If it is current, deactivating the old diverged current message has already unmasked it).

if not new.is_current: (2)

6. (NEW/CHANGED) If other is not already current, fork a diverged message. (If it is current, deactivating the old diverged current message has already unmasked it).

if not new.is_current:
    new.potemplate = current.potemplate
    new.is_current = True

7. Converge & activate.

new.potemplate = None # (watch for existing identical TM)
new.is_current = True

Capture the Flag

Look for a shared translation with the is_other flag set: 'other'.

*. If the merging policy says so and the other side is untranslated, assume the other flag as well:

    if other is None:
        new.is_other = True

⊕. Tracking. If the merging policy says so, steal the other flag:

    other.is_other = False
    new.is_other = True

By default, the policy should approve the change on is_other if working on upstream; or if working on Ubuntu but with privileges to edit both.

Execution matrix

Parenthesized elements are no-ops in their specific situations.

IDENTICAL EXISTING TM 'new'

None

shared

diverged

upstream shared

CURRENT

None

Z1*

Z4*

Z7*

Z4(*)

shared

B1*

B4*

B7*

B4(*)

diverged

A2

A5

A4

A6

upstream shared

B1⊕

B4⊕

B7⊕

(B4⊕)

Notes

A diverged message can mask a similar shared message as well. We tried to take this into account throughout, and believe we covered it. Conditionals in the numbered parts ("what happens to the new current message") may warrant splitting rows or columns later.

Karma is being handled.

Implementation notes

See lp:~jtv/launchpad/recife-552639

This implements two methods: one for setting the upstream translation, and one for setting the Ubuntu translation. An upstream translation also overrides Ubuntu translations; whether the converse also happens when translating in Ubuntu is determined by an optional argument.

The code calls the "current" message the "incumbent," and the "existing" message the "twin."

If the merging policy approves, the newly activated instruction will also receive the "other flag" if there is no current translation to steal it from.

Translations/Specs/UpstreamImportIntoUbuntu/FixingIsImported/setCurrentTranslation (last edited 2010-06-19 03:51:36 by jtv)