Author Topic: Storing and Displaying Translated Tags  (Read 1569 times)

karbock

  • Sr. Member
  • ****
  • Posts: 567
Storing and Displaying Translated Tags


If you wish to store two versions of some tags (original + translated),
the method proposed here uses:
  • one custom tag to store all the translations,
  • virtual tags, one for each translated piece of information.

Example used throughout this post

Let us take as example a track and its translation/transliteration:

Original
Translated/Transliterated
Album ArtistЧАЙКОВСКИЙ, ПётрTCHAIKOVSKY, Piotr
AlbumComplete Piano Works (vol. 4)
ArtistПОСТНИКОВА, ВикторияPOSTNIKOVA, Viktoria
ComposerЧАЙКОВСКИЙ, ПётрTCHAIKOVSKY, Piotr
WorkВремена годаThe Seasons
Movement NameДекабрь: СвяткиDecember: Christmas
TitleВремена года - 12. Декабрь: СвяткиThe Seasons - 12. December: Christmas

Custom tag

One custom tag suffices to store all the translations if you follow simple syntactic conventions.

Custom tag: TranslatedTags

Conventions:
  • Each piece of information is in the form {TagName:Value} or {TagCode:Value}.
  • Semicolons ; are optional, but allow for a clearer display with the tag inspector.
With our example, TranslatedTags will contain:
Code
{Album Artist:TCHAIKOVSKY, Piotr}; {Artist:POSTNIKOVA, Viktoria}; {Composer:TCHAIKOVSKY, Piotr}; {Work:The Seasons}; {Movement Name:December: Christmas}; {Title:The Seasons - 12. December: Christmas}
Or, with tag codes, and without the semicolons:
Code
{AA:TCHAIKOVSKY, Piotr}{AR:POSTNIKOVA, Viktoria}{CO:TCHAIKOVSKY, Piotr}{WO:The Seasons}{MO:December: Christmas}{TI:The Seasons - 12. December: Christmas}

NOTE:
  • If you already use { and } in your tags, choose other unique symbols.

Tag codes and tag names

  • AA = Album Artist
  • AR = Artist
  • TI = Title
  • CO = Composer
  • WO = Work
  • MO = Movement Name

Typical virtual tag formula

Virtual tag TranslatedArtist will display:
- the piece of information found in TranslatedTags within {Artist:} or {AR:} if it exists,
- Artist otherwise (inside an $IsNull declaration to prevent from displaying "Unknown Artist").

The matching formula is the following:
Code
$If(
    $IsMatch(<TranslatedTags>,"(?<={(Artist|AR)[:])[^}]*(?=})"),
    $RxMatch(<TranslatedTags>,"(?<={(Artist|AR)[:])[^}]*(?=})"),
    $IsNull(<Artist>,,<Artist>)
)
(Newlines and indentations have been added for the sake of readability.)

Comments:
  • [^}]* = a string containing no '}', possibly null
  • (?<={(Artist|AR)[:]) = the string must be preceded by '{Artist:' or '{AR:'
  • (?=}) = the string must be followed by '}'

Formulas for common tags

Just adapt the table to your needs:
- if you wish to use other separators;
- if you use other fields, such as Conductor, Lyricist, etc.

Virtual Tag
Formula
Result
TranslatedAlbumArtist$If($IsMatch(<TranslatedTags>,"(?<={(Album Artist|AA)[:])[^}]*(?=})"),$RxMatch(<TranslatedTags>,"(?<={(Album Artist|AA)[:])[^}]*(?=})"),$IsNull(<Album Artist>,,<Album Artist>))TCHAIKOVSKY, Piotr
TranslatedAlbum$If($IsMatch(<TranslatedTags>,"(?<={(Album|AL)[:])[^}]*(?=})"),$RxMatch(<TranslatedTags>,"(?<={(Album|AL)[:])[^}]*(?=})"),$IsNull(<Album>,,<Album>))
TranslatedArtist$If($IsMatch(<TranslatedTags>,"(?<={(Artist|AR)[:])[^}]*(?=})"),$RxMatch(<TranslatedTags>,"(?<={(Artist|AR)[:])[^}]*(?=})"),$IsNull(<Artist>,,<Artist>))POSTNIKOVA, Viktoria
TranslatedComposer$If($IsMatch(<TranslatedTags>,"(?<={(Composer|CO)[:])[^}]*(?=})"),$RxMatch(<TranslatedTags>,"(?<={(Composer|CO)[:])[^}]*(?=})"),$IsNull(<Composer>,,<Composer>))TCHAIKOVSKY, Piotr
TranslatedWork$If($IsMatch(<TranslatedTags>,"(?<={(Work|WO)[:])[^}]*(?=})"),$RxMatch(<TranslatedTags>,"(?<={(Work|WO)[:])[^}]*(?=})"),$IsNull(<Work>,,<Work>))The Seasons
TranslatedMovementName$If($IsMatch(<TranslatedTags>,"(?<={(Movement Name|MO)[:])[^}]*(?=})"),$RxMatch(<TranslatedTags>,"(?<={(Movement Name|MO)[:])[^}]*(?=})"),$IsNull(<Movement Name>,,<Movement Name>))December: Christmas
TranslatedTitle$If($IsMatch(<TranslatedTags>,"(?<={(Title|TI)[:])[^}]*(?=})"),$RxMatch(<TranslatedTags>,"(?<={(Title|TI)[:])[^}]*(?=})"),$IsNull(<Title>,,<Title>))The Seasons - 12. December: Christmas

References

MusicBee functions for virtual tags cheatsheet
Regular Expressions: coding, examples, testing resources
Last Edit: May 08, 2025, 04:17:58 PM by karbock

hiccup

  • Hero Member
  • *****
  • Posts: 9152
I was curious:
Are you using Picard to populate your tags?
If so, are you using a script for Picard to have this 'translated' custom tag created and filled automatically?

karbock

  • Sr. Member
  • ****
  • Posts: 567
I was curious:
Are you using Picard to populate your tags?
No, I have never used Picard, in fact.

When I add new tracks, I manually harmonise the format of their embedded tags with the existing collection (within mp3tag),
and so far I have populated TranslatedTags for only a small minority of albums (mainly world music or byzantine chants),
when the original title is in a rather obscure language but still readable.
I prefer having the original title as a reference, since the translations or transliterations can vary a lot.

But finding both the original title and a translation often requires to search on discogs + MusicBrainz + the rest of the internet.

nvxe

  • Newbie
  • *
  • Posts: 1
can you post an screenshot from the tag inspector with an example of how are the virtual tags within are supposed to look like?
i followed all your steps mentioned in https://getmusicbee.com/forum/index.php?topic=41923.0 but i don't know how to fill each, since only the "translatedtags" tag appears in tags(2)

karbock

  • Sr. Member
  • ****
  • Posts: 567
can you post an screenshot from the tag inspector with an example of how are the virtual tags within are supposed to look like?
i followed all your steps mentioned in https://getmusicbee.com/forum/index.php?topic=41923.0 but i don't know how to fill each, since only the "translatedtags" tag appears in tags(2)

Hello @nvxe, and welcome to the forum.

You need to populate TranslatedTags only.
The virtual tags are NOT populated by the user: they are computed "on the fly" each time they are displayed.
In other words, only the formula of a virtual tag is stored, not its resulting string.

As a concrete example, let's take one track from a Czech album.
  • ALBUM: "Klenoty českých vánoc", which translates to "Gems of Czech Christmas Carols"
  • TRACK 01 - TITLE: "Narodil se Kristus Pán", which means "Christ, Our Lord Was Born"

Step-by-step procedure:

STEP 01: Define custom tag "TranslatedTags"
Via Preferences > Tags(1) > button [Define new tags...]
In the first table, in a free slot, enter the value for TranslatedTags as in the picture on the right, and click on [Save].
STEP 02: Make "TranslatedTags" available in the interface
Via Preferences > Tags(1).
In a free custom tag slot, enter "TranslatedTags" in the left column, and select "TranslatedTags" in the right column.
STEP 03: Define virtual tags "TranslatedAlbum" and "TranslatedTitle"
Via Preferences > Tags(1) > button [Define new tags...]
In the second table, in two free slots, enter:

(1st one)
- as label: TranslatedAlbum
- as formula: $If($IsMatch(<TranslatedTags>,"(?<={(Album|AL)[:])[^}]*(?=})"),$RxMatch(<TranslatedTags>,"(?<={(Album|AL)[:])[^}]*(?=})"),$IsNull(<Album>,,<Album>))

(2nd one)
- as label: TranslatedTitle
- as formula: $If($IsMatch(<TranslatedTags>,"(?<={(Title|TI)[:])[^}]*(?=})"),$RxMatch(<TranslatedTags>,"(?<={(Title|TI)[:])[^}]*(?=})"),$IsNull(<Title>,,<Title>))
STEP 04: Populate "TranslatedTags"
* Right-click on track 01 > Edit > select tab "Tags(2)"
* Click on [...] to the right of "translatedtags"
* On the 1st row, let's enter for our example {Album:Gems of Czech Christmas Carols} (or {AL:Gems of Czech Christmas Carols})
* On the 2nd row, let's enter {Title:Christ, Our Lord Was Born} (or {TI:Christ, Our Lord Was Born})
* Click on [Update], then on [Save]

STEP 05: Use "TranslatedAlbum" and "TranslatedTitle" in the interface
One possible example here.
Last Edit: May 08, 2025, 04:20:16 PM by karbock