Localization support

This commit is contained in:
Jaidyn Ann 2021-03-21 18:47:58 -05:00
parent f67d0814a6
commit 1e7579ac08
17 changed files with 341 additions and 118 deletions

View File

@ -29,21 +29,21 @@ APP_MIME_SIG = application/x-vnd.Pogger
# same name (source.c or source.cpp) are included from different directories.
# Also note that spaces in folder names do not work well with this Makefile.
SRCS = \
src/App.cpp, \
src/AtomFeed.cpp, \
src/Entry.cpp, \
src/EntriesView.cpp, \
src/Feed.cpp, \
src/App.cpp \
src/AtomFeed.cpp \
src/Entry.cpp \
src/EntriesView.cpp \
src/Feed.cpp \
src/FeedController.cpp \
src/FeedEditWindow.cpp \
src/FeedListItem.cpp \
src/FeedsView.cpp, \
src/MainWindow.cpp, \
src/Mimetypes.cpp, \
src/Notifier.cpp, \
src/Preferences.cpp, \
src/RssFeed.cpp, \
src/UpdatesView.cpp, \
src/FeedsView.cpp \
src/MainWindow.cpp \
src/Mimetypes.cpp \
src/Notifier.cpp \
src/Preferences.cpp \
src/RssFeed.cpp \
src/UpdatesView.cpp \
src/Util.cpp
# Specify the resource definition files to use. Full or relative paths can be
@ -80,7 +80,7 @@ RSRCS = \
# - if your library does not follow the standard library naming scheme,
# you need to specify the path to the library and it's name.
# (e.g. for mylib.a, specify "mylib.a" or "path/mylib.a")
LIBS = be tracker bnetapi network netservices shared tinyxml2 $(STDCPPLIBS)
LIBS = be bnetapi localestub network netservices shared tinyxml2 tracker $(STDCPPLIBS)
# Specify additional paths to directories following the standard libXXX.so
# or libXXX.a naming scheme. You can specify full paths or paths relative
@ -111,7 +111,7 @@ OPTIMIZE := FULL
# will recreate only the "locales/en.catkeys" file. Use it as a template
# for creating catkeys for other languages. All localization files must be
# placed in the "locales" subdirectory.
LOCALES = en
LOCALES = en eo
# Specify all the preprocessor symbols to be defined. The symbols will not
# have their values set automatically; you must supply the value (if any) to

View File

@ -29,6 +29,7 @@ In "Updates" you can toggle notifications and set the frequency of updates.
## Building
`$ make`
`$ make bindcatalogs`
Uses netservices, and has TinyXML2 as a dependency.

View File

@ -1,7 +1,3 @@
Important Features:
* Localization
Improvements:
* Memory leaks
* ~.05MB per feed on download, in Util.ccp, fetch(). I'm stumped here.
* ~.02MB per feed on parsing

61
locales/en.catkeys Normal file
View File

@ -0,0 +1,61 @@
1 English application/x-vnd.Pogger 1418478689
Updates MainWindow Updates
Edit… FeedsView Edit…
Invalid Feed FeedEditWindow Invalid Feed
Never automatically update UpdatesView Never automatically update
Entries Directory EntriesView Entries Directory
{0, plural,=1{Failed to update %source% and one other.}other{Failed to update %source% and # others.}} Notifier {0, plural,=1{Failed to update %source% and one other.}other{Failed to update %source% and # others.}}
Browse… EntriesView Browse…
Entries MainWindow Entries
Feeds MainWindow Feeds
Feed name: FeedEditWindow Feed name:
Update Now MainWindow Update Now
There is not enough memory available on your system to load the preferences file.\nPlease try closing a few applications and restarting Pogger. Preferences There is not enough memory available on your system to load the preferences file.\nPlease try closing a few applications and restarting Pogger.
Select… EntriesView Select…
Scheduling UpdatesView Scheduling
{0, plural,=1{%n% new entries from %source% and one other.}other{%n% new entries from %source% and # others.}} Notifier {0, plural,=1{%n% new entries from %source% and one other.}other{%n% new entries from %source% and # others.}}
Open as: EntriesView Open as:
Couldn't open the preferences file because permission was denied.\nThis usually means that you don't have read permissions to your settings directory.\nPlease make sure that your user has read-access to your settings directory― likely %path%.\nCheck your OS documentation for more information. Preferences Couldn't open the preferences file because permission was denied.\nThis usually means that you don't have read permissions to your settings directory.\nPlease make sure that your user has read-access to your settings directory― likely %path%.\nCheck your OS documentation for more information.
Pogger System name Pogger
Update every 30 minutes UpdatesView Update every 30 minutes
Channel '%source%' at %url%:\n RssFeed Channel '%source%' at %url%:\n
Notify about new entries UpdatesView Notify about new entries
{0, plural,=1{Update every hour}other{Update every # hours}} UpdatesView {0, plural,=1{Update every hour}other{Update every # hours}}
OK EntriesView OK
Couldn't open this folder because no path was specified.\nPlease select a new folder. EntriesView Couldn't open this folder because no path was specified.\nPlease select a new folder.
Cancel MainWindow Cancel
Saving EntriesView Saving
Couldn't open the preferences file because the path is not specified.\nThis usually means that the programmer made a mistake.\nPlease submit a bug report to the Pogger repository on GitHub.\nYour personal settings will not be loaded. Preferences Couldn't open the preferences file because the path is not specified.\nThis usually means that the programmer made a mistake.\nPlease submit a bug report to the Pogger repository on GitHub.\nYour personal settings will not be loaded.
\t-%count% entries-\n RssFeed \t-%count% entries-\n
Update daily UpdatesView Update daily
HTML EntriesView HTML
Feed Updates Notifier Feed Updates
Notify about update failures UpdatesView Notify about update failures
Update Failure Notifier Update Failure
The path you selected isn't a folder― please choose another path. EntriesView The path you selected isn't a folder― please choose another path.
Untitled Feed Notifier Untitled Feed
24 hours UpdatesView 24 hours
There is not enough memory available on your system to access the given path.\nPlease try closing a few applications and restarting Pogger. EntriesView There is not enough memory available on your system to access the given path.\nPlease try closing a few applications and restarting Pogger.
Untitled Feed FeedListItem Untitled Feed
Never UpdatesView Never
Feed URL: FeedEditWindow Feed URL:
New Feed FeedEditWindow New Feed
Channel '%source%' at %url%:\n AtomFeed Channel '%source%' at %url%:\n
Downloading feed from FeedController Downloading feed from
URL EntriesView URL
Please enter a URL. FeedEditWindow Please enter a URL.
OK FeedEditWindow OK
Preferences file Preferences Preferences file
Notifications UpdatesView Notifications
Save FeedEditWindow Save
Failed to update %source%. Notifier Failed to update %source%.
Fetching %source%… FeedsView Fetching %source%…
{0, plural,=1{One new entry from %source%.}other{# new entries from %source%.}} Notifier {0, plural,=1{One new entry from %source%.}other{# new entries from %source%.}}
Edit Feed FeedEditWindow Edit Feed
Opening EntriesView Opening
The given URL is invalid. Please make sure you typed it in correctly. FeedEditWindow The given URL is invalid. Please make sure you typed it in correctly.
Delete FeedEditWindow Delete
Entry folder: EntriesView Entry folder:
\t-%count% entries-\n AtomFeed \t-%count% entries-\n
Couldn't open this folder because permission was denied.\nThis usually means that you don't have read permissions.\nPlease make sure that your user has read-access to this folder.\nCheck your OS documentation for more information. EntriesView Couldn't open this folder because permission was denied.\nThis usually means that you don't have read permissions.\nPlease make sure that your user has read-access to this folder.\nCheck your OS documentation for more information.
Open with: EntriesView Open with:

61
locales/eo.catkeys Normal file
View File

@ -0,0 +1,61 @@
1 Esperanto application/x-vnd.Pogger 1418478689
Updates MainWindow Ĝisdatigoj
Edit… FeedsView Redakti…
Invalid Feed FeedEditWindow Malvalida Fonto
Never automatically update UpdatesView Neniam ĝisdatigas aŭtomate
Entries Directory EntriesView Dosierujo de Afiŝoj
{0, plural,=1{Failed to update %source% and one other.}other{Failed to update %source% and # others.}} Notifier {0, plural,=1{Eraris ĝisdatigante %source% k alian.}other{Eraris ĝisdatigante %source% kaj # aliaj.}}
Browse… EntriesView Foliumi…
Entries MainWindow Afiŝoj
Feeds MainWindow Fontoj
Feed name: FeedEditWindow Fontonomo:
Update Now MainWindow Ĝisdatigi
There is not enough memory available on your system to load the preferences file.\nPlease try closing a few applications and restarting Pogger. Preferences Restas nesufiĉa kvanto de memoro je via sistmo, por ŝalti la agordan dosieron.\nBonvole provu malfermi kelkajn programojn, kaj poste restartigi Pogger.
Select… EntriesView Elekti…
Scheduling UpdatesView Tempoplano
{0, plural,=1{%n% new entries from %source% and one other.}other{%n% new entries from %source% and # others.}} Notifier {0, plural,=1{%n% novaj afiŝoj de %source% kaj alia.}other{%n% novaj afiŝoj de %source% kaj # aliaj.}}
Open as: EntriesView Malfermi kiel:
Couldn't open the preferences file because permission was denied.\nThis usually means that you don't have read permissions to your settings directory.\nPlease make sure that your user has read-access to your settings directory― likely %path%.\nCheck your OS documentation for more information. Preferences Neeblis malfermi la agordan dosieron, ĉar mankas permeso.\nTio probable signifas ke vi ne rajtas legi vian agordan dosierujon.\nBonvole certigi, ke via uzanto rajtas legi la agordan dosieron― probable %path%.\nReferenci vian funkcisisteman helpolibron, por lerni pli.
Pogger System name Pogger
Update every 30 minutes UpdatesView Ĝisdatigas duonhore
Channel '%source%' at %url%:\n RssFeed Fonoto '%source%' ĉe %url%:\n
Notify about new entries UpdatesView Sciigi pri novaj afiŝoj
{0, plural,=1{Update every hour}other{Update every # hours}} UpdatesView {0, plural,=1{Ĝisdatigas hore}other{Ĝisdatigas po # horoj}}
OK EntriesView Bone
Couldn't open this folder because no path was specified.\nPlease select a new folder. EntriesView Neeblis malfermi ĉi tiun dosierujon, ĉar la loko estas nedifinita.\nBonvole elektu novan dosierujon.
Cancel MainWindow Nuligi
Saving EntriesView Konservado
Couldn't open the preferences file because the path is not specified.\nThis usually means that the programmer made a mistake.\nPlease submit a bug report to the Pogger repository on GitHub.\nYour personal settings will not be loaded. Preferences Neeblis malfermi agordan dosieron ĉar la loko estas nedifinita.\nProbable tio signifas, ke la programisto eraris iel.\nBonvole raporti la problemon al la Pogger deponojo ĉe Github.\nViaj propraj agordoj ne ŝaltiĝos. Bedaŭron.
\t-%count% entries-\n RssFeed \t-%count% afiŝoj-\n
Update daily UpdatesView Ĝisdatigas tage
HTML EntriesView HTML
Feed Updates Notifier Fonto Ĝisdatigoj
Notify about update failures UpdatesView Sciigi pri eraroj ĝisdatigaj
Update Failure Notifier Eraris Ĝisdatigante
The path you selected isn't a folder― please choose another path. EntriesView La loko kiun vi elektis ne estas dosierujo― bonvole, elektu alian lokon.
Untitled Feed Notifier Sennoma Fonto
24 hours UpdatesView 24 horoj
There is not enough memory available on your system to access the given path.\nPlease try closing a few applications and restarting Pogger. EntriesView Restas nesufiĉa kvanto de memoro je via sistmo, por aliri tiun lokon.\nBonvole provu malfermi kelkajn programojn, kaj poste restartigi Pogger.
Untitled Feed FeedListItem Sennoma Fonto
Never UpdatesView Neniam
Feed URL: FeedEditWindow Fonto URL:
New Feed FeedEditWindow Nova Fonto
Channel '%source%' at %url%:\n AtomFeed Fonto '%source%' ĉe %url%:\n
Downloading feed from FeedController Elŝultante fonton de
Please enter a URL. FeedEditWindow Bonvole enigu URL-on.
URL EntriesView URL
OK FeedEditWindow Bone
Preferences file Preferences Agorda dosiero
Notifications UpdatesView Sciigoj
Save FeedEditWindow Konservi
Failed to update %source%. Notifier Eraris ĝisdatigante %source%.
Fetching %source%… FeedsView Elŝultante %source%…
{0, plural,=1{One new entry from %source%.}other{# new entries from %source%.}} Notifier {0, plural,=1{Nova afiŝo de %source%.}other{# novaj afiŝoj de %source%.}}
Edit Feed FeedEditWindow Redakti Fonton
Opening EntriesView Malfermado
The given URL is invalid. Please make sure you typed it in correctly. FeedEditWindow La enigita URL nevalidas. Bonvole, certigu ke vi ĝin ĝuste tajpis.
Delete FeedEditWindow Forigi
Entry folder: EntriesView Afiŝa dosierujo:
\t-%count% entries-\n AtomFeed \t-%count% afiŝoj-\n
Couldn't open this folder because permission was denied.\nThis usually means that you don't have read permissions.\nPlease make sure that your user has read-access to this folder.\nCheck your OS documentation for more information. EntriesView Neeblis malfermi la tiun dosierujon, ĉar mankas permeso.\nTio probable signifas ke vi ne rajtas legi ĝin.\n\nBonvole certigi, ke via uzanto rajtas legi ĝin.\nReferenci vian funkcisisteman helpolibron, por lerni pli.
Open with: EntriesView Malfermi per:

View File

@ -5,8 +5,6 @@
#include "App.h"
#include <iostream>
#include <MessageRunner.h>
#include <Roster.h>
#include <StorageKit.h>

View File

@ -7,6 +7,8 @@
#include <iostream>
#include <Catalog.h>
#include <tinyxml2.h>
#include "App.h"
@ -14,6 +16,10 @@
#include "Util.h"
#undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "AtomFeed"
AtomFeed::AtomFeed()
{
fTitle = BString("");
@ -65,8 +71,11 @@ AtomFeed::RootParse(tinyxml2::XMLElement* xfeed)
if (!set && xentry)
set = _SetDate(xentry->FirstChildElement("published"));
std::cout << "Channel '" << fTitle << "' at '" << fXmlUrl.UrlString()
<< "':\n";
BString logString(B_TRANSLATE("Channel '%source%' at %url%:\n"));
logString.ReplaceAll("%source%", fTitle.String());
logString.ReplaceAll("%url%", fXmlUrl.UrlString());
std::cout << logString.String();
}
@ -117,7 +126,12 @@ AtomFeed::ParseEntries(tinyxml2::XMLElement* xfeed)
int entryCount = _XmlCountSiblings(xentry, "entry");
fEntries = BObjectList<Entry>(entryCount, true);
std::cout << "\t-" << entryCount << "-\n";
BString logString(B_TRANSLATE("\t-%count% entries-\n"));
BString entryStr;
entryStr << entryCount;
logString.ReplaceAll("%count%", entryStr);
std::cout << logString.String();
while (xentry) {
EntryParse(xentry);

View File

@ -5,11 +5,10 @@
#include "EntriesView.h"
#include <iostream>
#include <Alert.h>
#include <Box.h>
#include <Button.h>
#include <Catalog.h>
#include <Message.h>
#include <LayoutBuilder.h>
#include <PopUpMenu.h>
@ -22,6 +21,10 @@
#include "Util.h"
#undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "EntriesView"
EntriesView::EntriesView(const char* name)
:
BGroupView(name, B_VERTICAL, B_USE_DEFAULT_SPACING)
@ -138,29 +141,31 @@ EntriesView::_InitInterface()
{
// Saving
fSavingBox = new BBox("saving");
fSavingBox->SetLabel("Saving");
fSavingBox->SetLabel(B_TRANSLATE("Saving"));
fEntryFolderLabel = new BStringView("entryFolderLabel", "Entry folder:");
fEntryFolderLabel = new BStringView("entryFolderLabel",
B_TRANSLATE("Entry folder:"));
fEntryFolderText = new BTextControl("entryFolder", "", "",
new BMessage(kEntryFolderText));
fEntryFolderBrowseButton = new BButton("entryFolderBrowse", "Browse…",
new BMessage(kEntryFolderBrowse));
fEntryFolderBrowseButton = new BButton("entryFolderBrowse",
B_TRANSLATE("Browse…"), new BMessage(kEntryFolderBrowse));
// Opening
fOpeningBox = new BBox("opening");
fOpeningBox->SetLabel("Opening");
fOpeningBox->SetLabel(B_TRANSLATE("Opening"));
fOpenAsLabel = new BStringView("openAsLabel", "Open as:");
fOpenAsHtmlRadio = new BRadioButton("asHtml", "HTML",
fOpenAsLabel = new BStringView("openAsLabel", B_TRANSLATE("Open as:"));
fOpenAsHtmlRadio = new BRadioButton("asHtml", B_TRANSLATE("HTML"),
new BMessage(kOpenHtmlRadio));
fOpenAsUrlRadio = new BRadioButton("asUrl", "URL",
fOpenAsUrlRadio = new BRadioButton("asUrl", B_TRANSLATE("URL"),
new BMessage(kOpenUrlRadio));
fOpenWithLabel = new BStringView("openWithLabel", "Open with:");
fOpenWithLabel = new BStringView("openWithLabel",
B_TRANSLATE("Open with:"));
fOpenWithMenu = new BPopUpMenu("openWith");
fOpenWithMenuField = new BMenuField("openWithMenu", NULL, fOpenWithMenu);
fOpenWithSelectButton = new BButton("openWithSelect", "Select…",
new BMessage(kOpenWithBrowse));
fOpenWithSelectButton = new BButton("openWithSelect",
B_TRANSLATE("Select…"), new BMessage(kOpenWithBrowse));
// Display current settings
@ -251,22 +256,24 @@ EntriesView::_FileError(status_t result)
find_directory(B_USER_SETTINGS_DIRECTORY, &cfgPath);
if (result == B_NOT_A_DIRECTORY) {
BAlert* alert = new BAlert("Entries Directory", "The path you "
"selected isn't a folder― please choose another path.", "OK",
NULL, NULL, B_WIDTH_AS_USUAL, B_WARNING_ALERT);
alert->Go();
BAlert* alert = new BAlert(B_TRANSLATE("Entries Directory"),
B_TRANSLATE("The path you selected isn't a folder― please choose "
"another path."), B_TRANSLATE("OK"), NULL, NULL,
B_WIDTH_AS_USUAL, B_WARNING_ALERT);
alert->Go();
return;
}
userFileError(result, "Entries Directory",
"Couldn't open this folder because no path was specified.\n"
"Please select a new folder.",
"Couldn't open this folder because permission was denied.\n"
userFileError(result, B_TRANSLATE("Entries Directory"),
B_TRANSLATE("Couldn't open this folder because no path was specified.\n"
"Please select a new folder."),
B_TRANSLATE("Couldn't open this folder because permission was denied.\n"
"This usually means that you don't have read permissions.\nPlease make "
"sure that your user has read-access to this folder.\nCheck your OS "
"documentation for more information.",
"There is not enough memory available on your system to access the "
"given path.\nPlease try closing a few applications and restarting Pogger.");
"documentation for more information."),
B_TRANSLATE("There is not enough memory available on your system to "
"access the given path.\nPlease try closing a few applications and "
"restarting Pogger."));
}

View File

@ -7,6 +7,7 @@
#include <iostream>
#include <Catalog.h>
#include <Directory.h>
#include <Message.h>
#include <MessageRunner.h>
@ -19,6 +20,10 @@
#include "RssFeed.h"
#undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "FeedController"
FeedController::FeedController()
:
fEnqueuedTotal(0),
@ -222,7 +227,7 @@ FeedController::_DownloadLoop(void* data)
Feed* feedBuffer = (Feed*)malloc(sizeof(Feed));
receive_data(&sender, (void*)feedBuffer, sizeof(Feed));
std::cout << "Downloading feed from "
std::cout << B_TRANSLATE("Downloading feed from ")
<< feedBuffer->XmlUrl().UrlString() << "\n";
if (feedBuffer->Fetch()) {

View File

@ -7,6 +7,7 @@
#include <Alert.h>
#include <Button.h>
#include <Catalog.h>
#include <Message.h>
#include <LayoutBuilder.h>
#include <SeparatorView.h>
@ -20,10 +21,15 @@
#include "Util.h"
#undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "FeedEditWindow"
FeedEditWindow::FeedEditWindow()
:
BWindow(((App*)be_app)->fPreferences->fFeedEditRect, "New Feed",
B_TITLED_WINDOW, B_NOT_RESIZABLE | B_NOT_ZOOMABLE)
BWindow(((App*)be_app)->fPreferences->fFeedEditRect,
B_TRANSLATE("New Feed"), B_TITLED_WINDOW,
B_NOT_RESIZABLE | B_NOT_ZOOMABLE)
{
_InitInterface();
MoveOnScreen();
@ -37,7 +43,7 @@ FeedEditWindow::FeedEditWindow(BEntry feedEntry)
:
FeedEditWindow()
{
SetTitle("Edit Feed");
SetTitle(B_TRANSLATE("Edit Feed"));
fFeed = Feed(feedEntry);
fFeedNameText->SetText(fFeed.Title().String());
@ -83,15 +89,15 @@ void
FeedEditWindow::_InitInterface()
{
// Name and URL
fFeedNameLabel = new BStringView("feedNameLabel", "Feed name:");
fFeedNameLabel = new BStringView("feedNameLabel", B_TRANSLATE("Feed name:"));
fFeedNameText = new BTextControl("feedName", "", "", NULL);
fFeedUrlLabel = new BStringView("feedUrlLabel", "Feed URL:");
fFeedUrlLabel = new BStringView("feedUrlLabel", B_TRANSLATE("Feed URL:"));
fFeedUrlText = new BTextControl("feedUrl", "", "", NULL);
// Save/Delete
fSaveButton = new BButton("save", "Save",
fSaveButton = new BButton("save", B_TRANSLATE("Save"),
new BMessage(kSaveButton));
fDeleteButton = new BButton("delete", "Delete",
fDeleteButton = new BButton("delete", B_TRANSLATE("Delete"),
new BMessage(kDeleteButton));
BLayoutBuilder::Group<>(this, B_VERTICAL, 0)
@ -147,17 +153,18 @@ FeedEditWindow::_SaveFeed()
BUrl url = BUrl(urlString);
if (BString(urlString).IsEmpty() == true) {
BAlert* emptyAlert = new BAlert("Invalid Feed",
"Please enter a URL.", "OK", NULL, NULL,
B_WIDTH_AS_USUAL, B_OFFSET_SPACING, B_WARNING_ALERT);
BAlert* emptyAlert = new BAlert(B_TRANSLATE("Invalid Feed"),
B_TRANSLATE("Please enter a URL."), B_TRANSLATE("OK"), NULL, NULL,
B_WIDTH_AS_USUAL, B_OFFSET_SPACING, B_WARNING_ALERT);
emptyAlert->Go();
return;
}
if (url.IsValid() == false) {
BAlert* invAlert = new BAlert("Invalid Feed",
"The given URL is invalid. Please make sure you typed it in correctly.",
"OK", NULL, NULL, B_WIDTH_AS_USUAL, B_OFFSET_SPACING, B_WARNING_ALERT);
BAlert* invAlert = new BAlert(B_TRANSLATE("Invalid Feed"),
B_TRANSLATE("The given URL is invalid. Please make sure you typed "
"it in correctly."), B_TRANSLATE("OK"), NULL, NULL,
B_WIDTH_AS_USUAL, B_OFFSET_SPACING, B_WARNING_ALERT);
invAlert->Go();
return;
}

View File

@ -5,12 +5,17 @@
#include "FeedListItem.h"
#include <Catalog.h>
#include <View.h>
#include "Feed.h"
#include "Util.h"
#undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "FeedListItem"
FeedListItem::FeedListItem(Feed* feed)
:
BStringItem(feed->Title().String(), 0, false),
@ -19,7 +24,7 @@ FeedListItem::FeedListItem(Feed* feed)
fFeedPath(feed->CachePath())
{
if (feed->Title().IsEmpty() == true)
SetText("Untitled Feed");
SetText(B_TRANSLATE("Untitled Feed"));
}

View File

@ -5,6 +5,7 @@
#include "FeedsView.h"
#include <Catalog.h>
#include <Message.h>
#include <GroupView.h>
#include <LayoutBuilder.h>
@ -22,6 +23,10 @@
#include "Notifier.h"
#undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "FeedsView"
FeedsView::FeedsView(const char* name)
:
BGroupView(name, B_VERTICAL, B_USE_DEFAULT_SPACING)
@ -121,7 +126,8 @@ FeedsView::_InitInterface()
// Add, Remove, Edit
fAddButton = new BButton("addFeed", "+", new BMessage(kFeedsAddButton));
fRemoveButton = new BButton("removeFeed", "-", new BMessage(kFeedsRemoveButton));
fEditButton = new BButton("editFeed", "Edit…", new BMessage(kFeedsEditButton));
fEditButton = new BButton("editFeed", B_TRANSLATE("Edit…"),
new BMessage(kFeedsEditButton));
font_height fontHeight;
GetFontHeight(&fontHeight);
@ -224,12 +230,12 @@ FeedsView::_UpdateProgress(BMessage* msg, int8 status)
BString feedName, feedUrl;
if (msg->FindString("feed_url", &feedUrl) != B_OK)
return;
if (msg->FindString("feed_name", &feedName) != B_OK)
if (msg->FindString("feed_name", &feedName) != B_OK || feedName.IsEmpty())
feedName = feedUrl;
if (status == kDownloadingStatus) {
BString label("Fetching ");
label << feedName << "";
BString label(B_TRANSLATE("Fetching %source%…"));
label.ReplaceAll("%source%", feedName);
fProgressLabel->SetText(label);
}

View File

@ -5,9 +5,8 @@
#include "MainWindow.h"
#include <iostream>
#include <Button.h>
#include <Catalog.h>
#include <GroupView.h>
#include <LayoutBuilder.h>
#include <SeparatorView.h>
@ -23,10 +22,14 @@
#include "UpdatesView.h"
#undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "MainWindow"
MainWindow::MainWindow()
:
BWindow(((App*)be_app)->fPreferences->fMainWindowRect, "Pogger",
B_TITLED_WINDOW, NULL)
BWindow(((App*)be_app)->fPreferences->fMainWindowRect,
B_TRANSLATE_SYSTEM_NAME("Pogger"), B_TITLED_WINDOW, 0)
{
_InitInterface();
MoveOnScreen();
@ -99,9 +102,9 @@ MainWindow::_InitInterface()
// Tabs
fBaseView = new BGroupView("baseView");
fTabView = new BTabView("tabView", B_WIDTH_FROM_WIDEST);
fFeedsView = new FeedsView("Feeds");
fEntriesView = new EntriesView("Entries");
fUpdatesView = new UpdatesView("Updates");
fFeedsView = new FeedsView(B_TRANSLATE("Feeds"));
fEntriesView = new EntriesView(B_TRANSLATE("Entries"));
fUpdatesView = new UpdatesView(B_TRANSLATE("Updates"));
fTabView->AddTab(fFeedsView);
fTabView->AddTab(fEntriesView);
@ -161,10 +164,10 @@ void
MainWindow::_SetUpdateButton(bool cancel)
{
if (cancel == true) {
fUpdateButton->SetLabel("Cancel");
fUpdateButton->SetLabel(B_TRANSLATE("Cancel"));
fUpdateButton->SetMessage(new BMessage(kClearQueue));
} else {
fUpdateButton->SetLabel("Update Now");
fUpdateButton->SetLabel(B_TRANSLATE("Update Now"));
fUpdateButton->SetMessage(new BMessage(kUpdateSubscribed));
}
}

View File

@ -5,14 +5,20 @@
#include "Notifier.h"
#include <Catalog.h>
#include <List.h>
#include <Message.h>
#include <StringFormat.h>
#include <Notification.h>
#include "App.h"
#include "FeedController.h"
#undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "Notifier"
Notifier::Notifier()
:
fFailedFeeds(new BList()),
@ -92,20 +98,31 @@ Notifier::_SendUpdatedNotification()
}
BNotification notifyNew(B_INFORMATION_NOTIFICATION);
BString notifyLabel("Feed Updates");
BString notifyText("%n% new entries from %source%");
BString notifyLabel(B_TRANSLATE("Feed Updates"));
BString notifyText;
static BStringFormat oneSourceFormat(B_TRANSLATE("{0, plural,"
"=1{One new entry from %source%.}"
"other{# new entries from %source%.}}"));
static BStringFormat multiSourceFormat(B_TRANSLATE("{0, plural,"
"=1{%n% new entries from %source% and one other.}"
"other{%n% new entries from %source% and # others.}}"));
if (fUpdatedFeeds->CountItems() > 1)
notifyText = "%n% new entries from %source% and %m% others";
multiSourceFormat.Format(notifyText, fUpdatedFeeds->CountItems() - 1);
else
oneSourceFormat.Format(notifyText, fTotalEntries);
BString entryNum,feedNum = "";
BString entryNum = "";
entryNum << fTotalEntries;
feedNum << fUpdatedFeeds->CountItems() - 1;
BString* feedTitle = (BString*)fUpdatedFeeds->ItemAt(0);
if (feedTitle->IsEmpty())
feedTitle->SetTo(B_TRANSLATE("Untitled Feed"));
notifyText.ReplaceAll("%n%", entryNum);
notifyText.ReplaceAll("%m%", feedNum);
notifyText.ReplaceAll("%source%",
((BString*)fUpdatedFeeds->ItemAt(0))->String());
notifyText.ReplaceAll("%source%", feedTitle->String());
notifyNew.SetTitle(notifyLabel);
notifyNew.SetContent(notifyText);
@ -127,18 +144,23 @@ Notifier::_SendFailedNotification()
}
BNotification notifyError(B_ERROR_NOTIFICATION);
BString notifyLabel("Update Failure");
BString notifyText("Failed to update %source%");
BString notifyLabel(B_TRANSLATE("Update Failure"));
BString notifyText;
static BStringFormat multiSourceFormat(B_TRANSLATE("{0, plural,"
"=1{Failed to update %source% and one other.}"
"other{Failed to update %source% and # others.}}"));
if (fFailedFeeds->CountItems() > 1)
notifyText = "Failed to update %source% and %m% others";
multiSourceFormat.Format(notifyText, fFailedFeeds->CountItems() - 1);
else
notifyText = B_TRANSLATE("Failed to update %source%.");
BString feedNum = "";
feedNum << fFailedFeeds->CountItems() - 1;
BString* feedTitle = (BString*)fFailedFeeds->ItemAt(0);
if (feedTitle->IsEmpty())
feedTitle->SetTo(B_TRANSLATE("Untitled Feed"));
notifyText.ReplaceAll("%m%", feedNum);
notifyText.ReplaceAll("%source%",
((BString*)fFailedFeeds->ItemAt(0))->String());
notifyText.ReplaceAll("%source%", feedTitle->String());
notifyError.SetTitle(notifyLabel);
notifyError.SetContent(notifyText);

View File

@ -5,11 +5,16 @@
#include "Preferences.h"
#include <Catalog.h>
#include <String.h>
#include "Util.h"
#undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "Preferences"
Preferences::Preferences() {
}
@ -189,22 +194,22 @@ Preferences::_FileError(status_t result)
BPath cfgPath;
find_directory(B_USER_SETTINGS_DIRECTORY, &cfgPath);
BString permLabel("Couldn't open the preferences file because permission "
"was denied.\nThis usually means that you don't have read permissions to "
"your settings directory.\nPlease make sure that your user has "
"read-access to your settings directory― likely %path%.\nCheck your OS "
"documentation for more information.");
BString permLabel(B_TRANSLATE("Couldn't open the preferences file because "
"permission was denied.\nThis usually means that you don't have read "
"permissions to your settings directory.\nPlease make sure that your user "
"has read-access to your settings directory― likely %path%.\nCheck your OS "
"documentation for more information."));
permLabel.ReplaceAll("%path%", cfgPath.Path());
userFileError(result, "Preferences file",
"Couldn't open the preferences file because the path is not "
"specified.\nThis usually means that the programmer made a mistake.\n"
userFileError(result, B_TRANSLATE("Preferences file"),
B_TRANSLATE("Couldn't open the preferences file because the path is "
"not specified.\nThis usually means that the programmer made a mistake.\n"
"Please submit a bug report to the Pogger repository on GitHub.\n"
"Your personal settings will not be loaded.",
"Your personal settings will not be loaded."),
permLabel.String(),
"There is not enough memory available on your system to load the "
"preferences file.\nPlease try closing a few applications and restarting "
"Pogger.");
B_TRANSLATE("There is not enough memory available on your system to "
"load the preferences file.\nPlease try closing a few applications and "
"restarting Pogger."));
}

View File

@ -7,11 +7,17 @@
#include <iostream>
#include <Catalog.h>
#include "App.h"
#include "Entry.h"
#include "Util.h"
#undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "RssFeed"
RssFeed::RssFeed()
{
fTitle = BString("");
@ -52,8 +58,11 @@ RssFeed::RootParse(tinyxml2::XMLElement* xchan)
_SetTitle(xchan->FirstChildElement("title"));
_SetDate(xchan->FirstChildElement("lastBuildDate"));
std::cout << "Channel '" << fTitle.String() << "' at '" << fXmlUrl.UrlString()
<< ":\n";
BString logString(B_TRANSLATE("Channel '%source%' at %url%:\n"));
logString.ReplaceAll("%source%", fTitle.String());
logString.ReplaceAll("%url%", fXmlUrl.UrlString());
std::cout << logString.String();
}
@ -86,7 +95,12 @@ RssFeed::ParseEntries(tinyxml2::XMLElement* xchan)
int entryCount = _XmlCountSiblings(xitem, "item");
fEntries = BObjectList<Entry>(entryCount, true);
std::cout << "\t-" << entryCount << " entries-\n";
BString logString(B_TRANSLATE("\t-%count% entries-\n"));
BString entryStr;
entryStr << entryCount;
logString.ReplaceAll("%count%", entryStr);
std::cout << logString.String();
while (xitem) {
EntryParse(xitem);

View File

@ -6,15 +6,21 @@
#include "UpdatesView.h"
#include <Box.h>
#include <Catalog.h>
#include <CheckBox.h>
#include <LayoutBuilder.h>
#include <Message.h>
#include <MessageRunner.h>
#include <LayoutBuilder.h>
#include <Slider.h>
#include <StringFormat.h>
#include "App.h"
#undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "UpdatesView"
UpdatesView::UpdatesView(const char* name)
:
BGroupView(name, B_VERTICAL, B_USE_DEFAULT_SPACING)
@ -73,24 +79,27 @@ UpdatesView::_InitInterface()
{
// Notifications
fNotificationsBox = new BBox("notifications");
fNotificationsBox->SetLabel("Notifications");
fNotificationsBox->SetLabel(B_TRANSLATE("Notifications"));
fNotifyNewCheck = new BCheckBox("newNotify", "Notify about new entries",
fNotifyNewCheck = new BCheckBox("newNotify",
B_TRANSLATE("Notify about new entries"),
new BMessage(kNotifyNewCheckbox));
fNotifyFailCheck = new BCheckBox("errorNotify",
"Notify about update failures", new BMessage(kNotifyFailCheckbox));
B_TRANSLATE("Notify about update failures"),
new BMessage(kNotifyFailCheckbox));
// Update scheduling
fSchedulingBox = new BBox("scheduling");
fSchedulingBox->SetLabel("Scheduling");
fSchedulingBox->SetLabel(B_TRANSLATE("Scheduling"));
fIntervalSlider =
new BSlider("interval", "Never automatically update",
new BSlider("interval", B_TRANSLATE("Never automatically update"),
new BMessage(kIntervalChanged), 0, 25, B_HORIZONTAL);
fIntervalSlider->SetHashMarkCount(26);
fIntervalSlider->SetHashMarks(B_HASH_MARKS_BOTTOM);
fIntervalSlider->SetLimitLabels("Never", "24 hours");
fIntervalSlider->SetLimitLabels(B_TRANSLATE("Never"),
B_TRANSLATE("24 hours"));
fIntervalSlider->SetModificationMessage(new BMessage(kIntervalChanged));
@ -160,19 +169,28 @@ UpdatesView::_UpdateIntervalLabel()
{
case -1:
{
newLabel = "Never automatically update";
newLabel = B_TRANSLATE("Never automatically update");
break;
}
case 0:
{
newLabel = "Update every 30 minutes";
newLabel = B_TRANSLATE("Update every 30 minutes");
break;
}
case 24:
{
newLabel = B_TRANSLATE("Update daily");
break;
}
default:
newLabel = "Update every %hour% hours";
{
static BStringFormat format(B_TRANSLATE("{0, plural,"
"=1{Update every hour}"
"other{Update every # hours}}"));
format.Format(newLabel, hours);
}
}
newLabel.ReplaceAll("%hour%", strHour);
fIntervalSlider->SetLabel(newLabel.String());
}