Localization facile d'interface

14:04 modifié dans API AppKit #1
L'idée peut paraà®tre méchante, mais il y une façon de localizer facilement une interface.
Je suis actuellement confronté au problème pour mes préférences, et j'ai, au final, opté pour cette méthode :

<br /><br />.h:<br />extern void localizeWindow(NSWindow *window);<br />extern void localizeView(NSView *view);<br />extern void localizeMenu(NSMenu *menu);<br /><br />.m:<br />static NSString&nbsp; &nbsp; *localizeString (NSString *string)<br />{<br />&nbsp; &nbsp; if (string == nil || [string length] == 0)<br />&nbsp; &nbsp; &nbsp; &nbsp; return string;<br />&nbsp; &nbsp; if ([[NSCharacterSet decimalDigitCharacterSet]<br />characterIsMember:[string characterAtIndex:0]])<br />&nbsp; &nbsp; &nbsp; &nbsp; return string;<br />&nbsp; &nbsp; return NSLocalizedString (string, @&quot;&quot;);<br />}<br /><br />static void localizeCell(NSCell *view)<br />{<br />&nbsp; &nbsp; if ([view respondsToSelector:@selector(title)] &amp;&amp; [view<br />respondsToSelector:@selector(setTitle:)])<br />&nbsp; &nbsp; &nbsp; &nbsp; [(NSButtonCell *)view setTitle:NSLocalizedString([view title],<br />@&quot;Cell title&quot;)];<br />&nbsp; &nbsp; if ([view respondsToSelector:@selector(stringValue)] &amp;&amp; [view<br />respondsToSelector:@selector(setStringValue:)])<br />&nbsp; &nbsp; &nbsp; &nbsp; [view setStringValue:NSLocalizedString([view stringValue],<br />@&quot;View stringValue&quot;)];<br />}<br /><br />static void localizeMatrix(NSMatrix *view)<br />{<br />&nbsp; &nbsp; NSEnumerator&nbsp; &nbsp; *cellEnum = [[view cells] objectEnumerator];<br />&nbsp; &nbsp; NSCell&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; *cell;<br /><br />&nbsp; &nbsp; while ((cell = [cellEnum nextObject]))<br />&nbsp; &nbsp; &nbsp; &nbsp; localizeCell(cell);<br />}<br /><br />void localizeWindow(NSWindow *window)<br />{<br />&nbsp; &nbsp; [window setTitle:NSLocalizedString([window title], @&quot;Window<br />title&quot;)];<br />&nbsp; &nbsp; [window setMiniwindowTitle:NSLocalizedString([window<br />miniwindowTitle], @&quot;Window title&quot;)];<br />&nbsp; &nbsp; localizeView([window contentView]);<br />}<br /><br />void localizeView(NSView *view)<br />{<br />&nbsp; &nbsp; NSEnumerator *subviewEnum = [[view subviews] objectEnumerator];<br />&nbsp; &nbsp; NSView&nbsp; &nbsp; *subview;<br /><br />&nbsp; &nbsp; while ((subview = [subviewEnum nextObject]))<br />&nbsp; &nbsp; &nbsp; &nbsp; localizeView(subview);<br /><br />&nbsp; &nbsp; if ([view toolTip])<br />&nbsp; &nbsp; &nbsp; &nbsp; [view setToolTip:localizeString([view toolTip])];<br /><br />&nbsp; &nbsp; if ([view isKindOfClass:[NSMatrix class]])<br />&nbsp; &nbsp; &nbsp; &nbsp; localizeMatrix((NSMatrix *) view);<br />&nbsp; &nbsp; else if ([view isKindOfClass:[NSPopUpButton class]])<br />&nbsp; &nbsp; &nbsp; &nbsp; localizeMenu((NSMenu *) view);<br />&nbsp; &nbsp; else if (![view isKindOfClass:[NSImageCell class]] &amp;&amp; ![view<br />isKindOfClass:[NSImageView class]])<br />&nbsp; &nbsp; {<br />&nbsp; &nbsp; &nbsp; &nbsp; if ([view respondsToSelector:@selector(title)] &amp;&amp; [view<br />respondsToSelector:@selector(setTitle:)])<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [(NSBox *)view setTitle:localizeString([(NSBox *)view<br />title])];<br />&nbsp; &nbsp; &nbsp; &nbsp; if ([view respondsToSelector:@selector(stringValue)] &amp;&amp; [view<br />respondsToSelector:@selector(setStringValue:)])<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [(NSTextField *)view<br />setStringValue:localizeString([(NSTextField *)view stringValue])];<br />&nbsp; &nbsp; }<br />}<br /><br />void localizeMenu(NSMenu *menu)<br />{<br />&nbsp; &nbsp; NSEnumerator&nbsp; &nbsp; *itemEnum = [[menu itemArray] objectEnumerator];<br />&nbsp; &nbsp; NSMenuItem&nbsp; &nbsp; &nbsp; &nbsp; *item;<br /><br />&nbsp; &nbsp; [menu setTitle:localizeString([menu title])];<br />&nbsp; &nbsp; while ((item = [itemEnum nextObject]))<br />&nbsp; &nbsp; {<br />&nbsp; &nbsp; &nbsp; &nbsp; [item setTitle:localizeString([item title])];<br />&nbsp; &nbsp; &nbsp; &nbsp; localizeMenu([item submenu]);<br />&nbsp; &nbsp; }<br />}<br />


Je me suis dit que ça pourrait servir à  quelques-uns d'entre nous.
Il ne reste pas moins nécessaire de localizer le XIB afin de prévoir d'éventuels changement côté layout du fait que la longueur des textes peuvent changer facilement selon les langues.

Réponses

  • devulderdevulder Membre
    octobre 2010 modifié #2
    dans 1286612863:

    L'idée peut paraà®tre méchante, mais il y une façon de localizer facilement une interface.
    Je suis actuellement confronté au problème pour mes préférences, et j'ai, au final, opté pour cette méthode :

    <br /><br />.h:<br />extern void localizeWindow(NSWindow *window);<br />extern void localizeView(NSView *view);<br />extern void localizeMenu(NSMenu *menu);<br /><br />.m:<br />static NSString&nbsp; &nbsp; *localizeString (NSString *string)<br />{<br />&nbsp; &nbsp; if (string == nil || [string length] == 0)<br />&nbsp; &nbsp; &nbsp; &nbsp; return string;<br />&nbsp; &nbsp; if ([[NSCharacterSet decimalDigitCharacterSet]<br />characterIsMember:[string characterAtIndex:0]])<br />&nbsp; &nbsp; &nbsp; &nbsp; return string;<br />&nbsp; &nbsp; return NSLocalizedString (string, @&quot;&quot;);<br />}<br /><br />static void localizeCell(NSCell *view)<br />{<br />&nbsp; &nbsp; if ([view respondsToSelector:@selector(title)] &amp;&amp; [view<br />respondsToSelector:@selector(setTitle:)])<br />&nbsp; &nbsp; &nbsp; &nbsp; [(NSButtonCell *)view setTitle:NSLocalizedString([view title],<br />@&quot;Cell title&quot;)];<br />&nbsp; &nbsp; if ([view respondsToSelector:@selector(stringValue)] &amp;&amp; [view<br />respondsToSelector:@selector(setStringValue:)])<br />&nbsp; &nbsp; &nbsp; &nbsp; [view setStringValue:NSLocalizedString([view stringValue],<br />@&quot;View stringValue&quot;)];<br />}<br /><br />static void localizeMatrix(NSMatrix *view)<br />{<br />&nbsp; &nbsp; NSEnumerator&nbsp; &nbsp; *cellEnum = [[view cells] objectEnumerator];<br />&nbsp; &nbsp; NSCell&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; *cell;<br /><br />&nbsp; &nbsp; while ((cell = [cellEnum nextObject]))<br />&nbsp; &nbsp; &nbsp; &nbsp; localizeCell(cell);<br />}<br /><br />void localizeWindow(NSWindow *window)<br />{<br />&nbsp; &nbsp; [window setTitle:NSLocalizedString([window title], @&quot;Window<br />title&quot;)];<br />&nbsp; &nbsp; [window setMiniwindowTitle:NSLocalizedString([window<br />miniwindowTitle], @&quot;Window title&quot;)];<br />&nbsp; &nbsp; localizeView([window contentView]);<br />}<br /><br />void localizeView(NSView *view)<br />{<br />&nbsp; &nbsp; NSEnumerator *subviewEnum = [[view subviews] objectEnumerator];<br />&nbsp; &nbsp; NSView&nbsp; &nbsp; *subview;<br /><br />&nbsp; &nbsp; while ((subview = [subviewEnum nextObject]))<br />&nbsp; &nbsp; &nbsp; &nbsp; localizeView(subview);<br /><br />&nbsp; &nbsp; if ([view toolTip])<br />&nbsp; &nbsp; &nbsp; &nbsp; [view setToolTip:localizeString([view toolTip])];<br /><br />&nbsp; &nbsp; if ([view isKindOfClass:[NSMatrix class]])<br />&nbsp; &nbsp; &nbsp; &nbsp; localizeMatrix((NSMatrix *) view);<br />&nbsp; &nbsp; else if ([view isKindOfClass:[NSPopUpButton class]])<br />&nbsp; &nbsp; &nbsp; &nbsp; localizeMenu((NSMenu *) view);<br />&nbsp; &nbsp; else if (![view isKindOfClass:[NSImageCell class]] &amp;&amp; ![view<br />isKindOfClass:[NSImageView class]])<br />&nbsp; &nbsp; {<br />&nbsp; &nbsp; &nbsp; &nbsp; if ([view respondsToSelector:@selector(title)] &amp;&amp; [view<br />respondsToSelector:@selector(setTitle:)])<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [(NSBox *)view setTitle:localizeString([(NSBox *)view<br />title])];<br />&nbsp; &nbsp; &nbsp; &nbsp; if ([view respondsToSelector:@selector(stringValue)] &amp;&amp; [view<br />respondsToSelector:@selector(setStringValue:)])<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [(NSTextField *)view<br />setStringValue:localizeString([(NSTextField *)view stringValue])];<br />&nbsp; &nbsp; }<br />}<br /><br />void localizeMenu(NSMenu *menu)<br />{<br />&nbsp; &nbsp; NSEnumerator&nbsp; &nbsp; *itemEnum = [[menu itemArray] objectEnumerator];<br />&nbsp; &nbsp; NSMenuItem&nbsp; &nbsp; &nbsp; &nbsp; *item;<br /><br />&nbsp; &nbsp; [menu setTitle:localizeString([menu title])];<br />&nbsp; &nbsp; while ((item = [itemEnum nextObject]))<br />&nbsp; &nbsp; {<br />&nbsp; &nbsp; &nbsp; &nbsp; [item setTitle:localizeString([item title])];<br />&nbsp; &nbsp; &nbsp; &nbsp; localizeMenu([item submenu]);<br />&nbsp; &nbsp; }<br />}<br />
    


    Je me suis dit que ça pourrait servir à  quelques-uns d'entre nous.
    Il ne reste pas moins nécessaire de localizer le XIB afin de prévoir d'éventuels changement côté layout du fait que la longueur des textes peuvent changer facilement selon les langues.


    Merci,

    Il me semble que tu as oublier les NSBox qui ont une méthode spécifique pour le titre (si je me rappelle bien).

    Il y aussi la présentation faites a CocoaHeads voir ici pour le slide.

  • 14:04 modifié #3
    <br />if ([view respondsToSelector:@selector(title)] &amp;&amp; [view<br />respondsToSelector:@selector(setTitle:)])<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [(NSBox *)view setTitle:localizeString([(NSBox *)view<br />title])];<br />
    


    C'est déjà  dedans  :D
    Ceci-dit, le code ne vient pas de moi (je préfère préciser).

    J'ai retranscris le code en Objective-C pour le nom des méthodes

    <br />+ (NSString*)localizeString:(NSString*)aString<br />{<br />&nbsp; &nbsp; if (aString == nil || [aString length] == 0)<br />&nbsp; &nbsp; &nbsp; &nbsp; return aString;<br />&nbsp; &nbsp; if ([[NSCharacterSet decimalDigitCharacterSet]<br />		 characterIsMember:[aString characterAtIndex:0]])<br />&nbsp; &nbsp; &nbsp; &nbsp; return aString;<br />&nbsp; &nbsp; return NSLocalizedString (aString, @&quot;&quot;);<br />}<br /><br />+ (void)localizeCell:(NSCell*)aCell<br />{<br />	if ([aCell respondsToSelector:@selector(title)] &amp;&amp; [aCell<br />													&nbsp;  respondsToSelector:@selector(setTitle:)])<br />&nbsp; &nbsp; &nbsp; &nbsp; [(NSButtonCell *)aCell setTitle:NSLocalizedString([aCell title],<br />														 @&quot;&quot;)];<br />&nbsp; &nbsp; if ([aCell respondsToSelector:@selector(stringValue)] &amp;&amp; [aCell<br />															 respondsToSelector:@selector(setStringValue:)])<br />&nbsp; &nbsp; &nbsp; &nbsp; [aCell setStringValue:NSLocalizedString([aCell stringValue],<br />											&nbsp;  @&quot;&quot;)];<br />}<br /><br />+ (void)localizeMenu:(NSMenu*)aMenu<br />{<br />	NSEnumerator&nbsp; &nbsp; *itemEnum = [[aMenu itemArray] objectEnumerator];<br />	NSMenuItem&nbsp; &nbsp; &nbsp; &nbsp; *item;<br />	<br />	[aMenu setTitle:[ECPreferencesController localizeString:[aMenu title]]];<br />	while ((item = [itemEnum nextObject]))<br />	{<br />		[item setTitle:[ECPreferencesController localizeString:[item title]]];<br />		[ECPreferencesController localizeMenu:[item submenu]];<br />	}<br />}<br /><br /><br />+ (void)localizeView:(NSView*)aView<br />{<br />	NSEnumerator *subviewEnum = [[aView subviews] objectEnumerator];<br />&nbsp; &nbsp; NSView&nbsp; &nbsp; *subview;<br />	<br />&nbsp; &nbsp; while ((subview = [subviewEnum nextObject]))<br />&nbsp; &nbsp; &nbsp; &nbsp; [ECPreferencesController localizeView:subview];<br />	<br />&nbsp; &nbsp; if ([aView toolTip])<br />&nbsp; &nbsp; &nbsp; &nbsp; [aView setToolTip:[ECPreferencesController localizeString:[aView toolTip]]];<br />	<br />	if ([aView isKindOfClass:[NSPopUpButton class]])<br />&nbsp; &nbsp; &nbsp; &nbsp; [ECPreferencesController localizeMenu:(NSMenu*)aView];<br />&nbsp; &nbsp; else if (![aView isKindOfClass:[NSImageCell class]] &amp;&amp; ![aView<br />															isKindOfClass:[NSImageView class]])<br />&nbsp; &nbsp; {<br />&nbsp; &nbsp; &nbsp; &nbsp; if ([aView respondsToSelector:@selector(title)] &amp;&amp; [aView<br />														&nbsp;  respondsToSelector:@selector(setTitle:)])<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [(NSBox *)aView setTitle:[ECPreferencesController localizeString:[(NSBox *)aView title]]];<br />&nbsp; &nbsp; &nbsp; &nbsp; if ([aView respondsToSelector:@selector(stringValue)] &amp;&amp; [aView respondsToSelector:@selector(setStringValue:)])<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [(NSTextField *)aView setStringValue:[ECPreferencesController localizeString:[(NSTextField *)aView stringValue]]];<br />&nbsp; &nbsp; }<br />}<br />
    


    Concernant l'utilisation, y'a rien de plus simple.
    <br />- (void)awakeFromNib{<br />	[ECPreferencesController localizeView:self.view];<br />}<br />
    

    Et concernant les performances.. de mon côté je n'ai rien à  reproché au code.
  • CéroceCéroce Membre, Modérateur
    14:04 modifié #4
    J'ai pondu un article à  ce propos il y a quelques jours.
Connectez-vous ou Inscrivez-vous pour répondre.