WPF w wielu językach

Jeżeli będziecie kiedyś w potrzebie zaimplementowania obsługi kilku języków w aplikacji opartej na WPF, to możecie skorzystać z tego wpisu. Nie jest to moje rozwiązanie, a raczej opracowanie artykułu znalezionego na codeproject. Jeżeli coś nie będzie działa, nie będzie jasne, czy w ogóle nie będzie to pytania kierujcie do mnie lub bezpośrednio do autora artykułu na codeproject. To co tutaj zamierzam umieścić, to tylko kilka kroków, które podsumowują całą pracę potrzebną do implementacji interesującej nas funkcjonalności. To tyle tytułem wyjaśnienia i wprowadzenia.
Nazwy klas odpowiadają tym, które zostały użyte w kodzie dostępnym pod tym adresem. Kod w przykładzie z codeproject używa innych nazw.

Kroki potrzebne do zaimplementowania funkcjonalności:
1) Utwórz projekt
2) Utwórz katalog w projekcie. W katalogu będziesz trzymać zasoby. Oraz implementacje klasy, zwracającej instancje zasobów, oraz obsługującej zmianę aktualnego języka
3) Dodaj zasoby do projektu
3a) Ustaw custom namespace na wpfMUI.Properties (wpfMUI to nazwa mojego projektu)
3b) Usuń domyślne zasoby z Properties
4) Utwórz klasę LocalResources
4a) Prze(pisz|kopiuj) kod klasy
5) Dodaj do projektu ResourceDictionary
5a)Prze(pisz|kopiuj) kod
6) W app.xaml dodaj ResourceDictionary do zasobów aplikacji, prze(pisz|kopiuj)
7) W Properties.Settings ustaw domyślną wartość dla CultureInfo, w przykładnie “en” jest domyślny
8) W inicjalizacji głównego okna skorzystaj z tej wartości, przeczytaj komentarz w projekcie.
9) Podepnij obsługę comboboxa, pamiętaj to tylko przykład. W normalnym projekcie, kto inny będzie informować klasę LocalResources o zmianach.
10) W zasobach ustaw dostęp na publiczny
10a) Stwórz kopie zasobów, zmień nazwę na Resources.en.resx
10b) Zrób kopie i zmień nazwę na Resources.pl.resx
10c) Ustaw odpowiednie wartości dla poszczególnych wersji językowych
11) Ustaw właściwy content dla kontrolek, np dla guzika:

Content="{Binding Path=buttonText, Source={StaticResource Resources}}"

Dla combobox:

ItemsSource="{Binding Mode=OneTime, Path=SupportedCultures,Source={StaticResource SuppCultures}}

Możesz też użyć ustawiania właściwości dla kontrolek, ale zauważyłem że Path i tak należy ustawić ręcznie.

Po tym wszystkim, możesz próbować kompilować projekt i odpalać. Potem tylko drobne poprawki i wszystko powinno działać. Projekt jak często można pobrać z xp-dev

Cieszysz się?

Porządek musi być

Pracuję mozolnie nad tajnym projektem i nawet jeżeli nie przyniesie potrzebnych milionów to przynajmniej zajmie trochę czasu, a może nauczę się czegoś. Ale nie o tym miałem pisać. Chodzi o porządki. Do tej pory pisałem sobie o wszystkim co miałem zrobić zgrabnie w kajeciku. Zapisywałem w zasadzie wszystko związane z projektem i wykorzystywaną technologią: co do zrobienia, jak zrobić to i tamto, jakieś sprawy o których miałem pomyśleć. Nawet dawało rade – nawet. Z czasem natłok zapisków zaczął powodować pewien brak czytelności, dla rozróżnienia wpisów dodawałem sobie “checkbox” przy rzeczach które wymagały zrobienia, wykrzykniki przy cennych 😉 uwagach, czy znaki zapytania przy sprawach wymagających przemyślenia. Działało nawet lepiej, ale nadal mieszało się z ogólnymi notatkami. Dzisiaj przesiadłem na się na góglowego eksela, a przynajmniej częściowo. Listę zadań do zrobienia i przemyślenia całkowicie przeniosłem w chmurę, dodałem status, priorytet, opis i kolory. Jak szaleć to szaleć. Mam nadzieję, że w ten sposób uda mi się trzymać listę rzeczy do zrobienia bardziej przejrzystą. Myślałem przez chwilę o zainstalowaniu jakiegoś wypasionego toola, ale uznałem to za przerost treści nad formą.

Tak tylko chciałem się tym z wami (moi wierni ninja czytelnicy) podzielić. Jak macie jakieś inne, może lepsze sposoby na prowadzenie swoich projektów to pisać.

Time Counter

Się porobiło. Napisałem prosty programik, który pozwoli na sprawdzenie na co marnuje czas siedząc przed komputerem. Aplikacja prosta i pełna błędów.
Jeżeli kogoś zainteresuje to źródła są tam xp-dev, a binarka tam TimeCounter.7z.Działanie jest nie skomplikowane, aplikacja co zadany czas sprawdza jaka jest nazwa aktywnego okna, lub jaka jest nazwa procesu którego okno ma aktualnie focus i dodaje do licznika. Ot i tyle. Wymaga .net 3.5 wybaczcie mi za to, ale uczę się c# i dlatego w tym klikam.

Pytania? Drwiny? Sugestie?

//edit
W ramach aktywności blogowej dodałem brakujący tytuł.

Własny moduł w Joomla!

Dużo klikam w tym frameworku ENG i PL ostatnimi czasu, więc postanowiłem się podzielić swą nikłą wiedzą. Na początek info jak stworzyć własny moduł. Jak piszą w różnych artykułach i książkach moduł ogranicza się najczęściej do wyświetlenia prostych informacji. W standardowej instalacji joomli nie znajdzie się link z możliwością wylogowania użytkownika. Potrzebowałem takiej funkcjonalności więc napisałem kilka linii kodu, które dodają taką możliwość. Jedyne czego nie ma tutaj to jakieś sensowne wyświetlenie tego na stronie. Ale każdy (poza mną) kto zna się na CSS na pewno sobie z tym poradzi.
Mój moduł korzysta z komponentu user, który jest w każdej instalacji joomla. Jeżeli ktoś będzie używać Community Builder, wystarczy podmienić komponent i taski. Niektóre się pokrywają. Ja zrezygnowałem z tego rozszerzenia, ponieważ nie pozwala on na taką konfiguracje, której potrzebowałem. Poza tym nie chciałem płacić za pozbycie się odnośnika do ich strony.
Przejdźmy do rzeczy, z braku lepszego pomysłu nazwę moduł login2. Wszystkie modułu w joomla mają prefix mod, wiec właściwa nazwa będzie mod_login2. Mamy nazwę, teraz trzeba stworzyć plik z kodem php.

mod_login2.php

<?php
defined( '_JEXEC' ) or die( __FILE__.' - restricted access' );

if( JFactory::getUser()->guest )
{
    $link1 = "<a href=index.php?option=com_user&view=login>Logowanie</a>";
    $link2 = "<a href=index.php?option=com_user&task=register>Rejestracja</a>";
}
else
{
    $link1 = '<a href=index.php?option=com_user&view=user&layout=form>Profil</a>';
    $link2 = '<a href=index.php?option=com_user&task=logout>Wylogowanie</a>';
}
$display = $params->get( 'DisplayUserName', 0 );
if( $display )
{
    $username = JFactory::getUser()->name;
    if(!isset($username))
    {
        $username = "Gość";
    }
}
?>
<div class="Login">
    <?php
    if( $display )
    {
        echo '<span class="username">';
        echo $username;
        echo '</span>';
    }
    ?>
    <span class="action1">
        <?php echo $link1;?>
    </span>
    <span class="action2">
        <?php echo $link2;?>
    </span>
</div>

I teraz kilka słów uwagi:
@2 – Pisząc w joomla nie zezwala się na bezpośrednio dostęp do kodu, zawsze musi to zostać wywołane przez framework. Jeżeli ktoś chce być bardziej chytry niż my czeka go nie miła niespodzianka. Dodatek w postaci __FILE__ jest tylko dla nas, na wypadek gdybyśmy sami się przechytrzyli i nie wiedzieli gdzie.
@4 – Sprawdzamy czy aktualny użytkownik się zalogował czy jest anonimowym surferem.
@6,7 i 11,12 – w zależności czy stanu zalogowaniu ustawiamy właściwe linki logowanie, rejestracja lub (po zalogowaniu) profil i wyloguj.
@14 – z ustawień modułu pobieramy ustawienia, a tym za chwile. Decydujemy czy chcemy wyświetlić dodatkową linie z nazwą użytkownika lub @20 – gość.
@24 i dalej – tutaj już prawie czysty kod html z prostą wstawką php. Teraz jest to wrzucone w div, natomiast jeżeli jest przygotowane miejsce w template (jak to się odmienia?) to w ustawieniach użytkownika można wybrać pozycje, gdzie linki powinny się znajdować. Na razie skorzystam z div i span.

Dodatkowy plik z konfiguracja modułu, przydatny podczas instalacji i konfiguracji (@14)

mod_login2.xml

<?xml version="1.0" encoding="UTF-8"?>
<install type="module" version="1.5">
    <name>Login2</name>
    <author>js</author>
    <creationDate>2010</creationDate>
    <copyright>Some</copyright>
    <licence>GPL</licence>
    <authorEmail>jaroslawKROPKAstadnickiMAŁPKAgmailKROPKAcom</authorEmail>
    <authorUrl>jsthedeveloper.blogspot.com</authorUrl>
    <version>1.0</version>
    <description>Moduł wyświetlający dodatkowe opcje logowania</description>
    <files>
        <filename module="mod_fplogin">mod_login2.php</filename>
    </files>

    <params>
        <param name="DisplayUserName" type="radio" default="0" label="Wyswietlić nazwę użytkownika" description="Wyświetla dodatkową linię z nazwa zalogowanego użytkownika, lub gość jeżeli osobnik nie podjął się trudu logowania">
            <option value="0">No</option>
            <option value="1">Yes</option>
        </param>
    </params>
</install>

I lecimy z opisem:
@2 – info że to moduł
@wszystko aż do 12 – bla bla bla opisy, kto, kiedy i gdzie go można znaleźć wszystko widoczne po instalacji modułu.
@12:14 – lista plików wchodzących w skład modułu. Można dodawać podkatalogi jeżeli ktoś lubi porządek i ma więcej niż jeden plik.
@16 – tutaj zaczyna się lista parametrów
@17 – name Poprzez ten identyfikator będziemy się odnosić do tego parametru, patrz php linia 14
type – tutaj korzystam z prostego wyboru 1/0, test zamknięty nie można się pomylić. Radio button może zawierać więcej niż dwa pola.
label Nazwa którą zobaczy użytkownik w panelu admina.
description popup który się pojawi jak mysz zatrzyma się na dłużej nad polem.

Jak instalować?

Są trzy sposoby, ale tylko dwa normalne.
1) Spakować do zipa i wskazać zipa jako źródło instalacji
2) Trzymać w jakimś katalogu i wskazać katalog jako źródło instalacji
3) Skopiować do joomli do katalogu modulesmod_login2 i potem zhakować bazę danych. Jako że to jest głupi pomysł nie będę tej myśli rozwijać bardziej.

Na bank gdzieś coś pomyliłem. Pytania?