summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon McVittie <simon.mcvittie@collabora.co.uk>2014-03-25 09:45:30 +0000
committerSimon McVittie <simon.mcvittie@collabora.co.uk>2014-03-25 09:45:30 +0000
commitdf15a2e6ece1afa76425fd1186710afd567ff321 (patch)
tree95fd075ee5d60b2637949a64958aab1ab9f1e567
parentf27bd6cdf16f258d0ad76ab5222cc74c64796a11 (diff)
parent766510d2ae84cd04a770626a76029447bc4cdf66 (diff)
Merge branch 'master' into next
-rw-r--r--HACKING5
-rw-r--r--NEWS4
-rwxr-xr-xautogen.sh13
-rw-r--r--backends/bluez/Makefile.am1
-rw-r--r--backends/bluez/bluez-backend-factory.vala31
-rw-r--r--backends/bluez/bluez-backend.vala29
-rw-r--r--backends/bluez/bluez-persona-store.vala110
-rw-r--r--backends/bluez/bluez-persona.vala305
-rw-r--r--backends/dummy/lib/dummy-full-persona.vala15
-rw-r--r--backends/dummy/lib/dummy-persona.vala30
-rw-r--r--backends/eds/eds-backend.vala14
-rw-r--r--backends/eds/lib/edsf-persona-store.vala35
-rw-r--r--backends/eds/lib/edsf-persona.vala3
-rw-r--r--backends/tracker/lib/trf-persona-store.vala9
-rw-r--r--check.mk1
-rw-r--r--configure.ac25
-rw-r--r--docs/Makefile.am1
-rw-r--r--folks/anti-linkable.vala70
-rw-r--r--folks/backend-store.vala12
-rw-r--r--folks/individual-aggregator.vala19
-rw-r--r--m4/vala.m470
-rw-r--r--po/da.po367
-rw-r--r--po/fr.po475
-rw-r--r--po/it.po360
-rw-r--r--po/ko.po370
-rw-r--r--po/lv.po353
-rw-r--r--po/nb.po340
-rw-r--r--po/pt.po358
-rw-r--r--po/ru.po342
-rw-r--r--tests/Makefile.am7
-rw-r--r--tests/bluez/Makefile.am48
-rw-r--r--tests/bluez/device-properties.vala305
-rw-r--r--tests/bluez/individual-retrieval.vala232
-rw-r--r--tests/bluez/vcard-parsing.vala255
-rw-r--r--tests/dummy/Makefile.am5
-rw-r--r--tests/dummy/linkable-properties.vala275
-rw-r--r--tests/eds/Makefile.am12
-rw-r--r--tests/eds/helper-create-many-contacts.vala2
-rw-r--r--tests/eds/helper-delete-contacts.vala2
-rw-r--r--tests/eds/helper-prepare-aggregator.vala2
-rw-r--r--tests/folks/Makefile.am4
-rw-r--r--tests/lib/Makefile.am12
-rw-r--r--tests/lib/bluez/Makefile.am51
-rw-r--r--tests/lib/bluez/backend.vala306
-rw-r--r--tests/lib/bluez/test-case.vala127
-rw-r--r--tests/lib/dummy/Makefile.am1
-rw-r--r--tests/lib/eds/Makefile.am1
-rw-r--r--tests/lib/eds/test-case.vala96
-rw-r--r--tests/lib/folks-test-dbus.vapi52
-rw-r--r--tests/lib/gtestdbus.c941
-rw-r--r--tests/lib/gtestdbus.h90
-rw-r--r--tests/lib/key-file/Makefile.am1
-rw-r--r--tests/lib/libsocialweb/Makefile.am1
-rw-r--r--tests/lib/org-freedesktop-dbus-mock.vala124
-rw-r--r--tests/lib/telepathy/Makefile.am9
-rw-r--r--tests/lib/telepathy/test-case.vala5
-rw-r--r--tests/lib/test-case.vala158
-rw-r--r--tests/lib/test-utils.vala92
-rw-r--r--tests/lib/tracker/Makefile.am1
-rw-r--r--tests/lib/tracker/test-case.vala66
-rw-r--r--tests/libsocialweb/Makefile.am4
-rw-r--r--tests/telepathy/Makefile.am5
-rw-r--r--tests/test.mk1
-rw-r--r--tests/tools/Makefile.am7
-rw-r--r--tests/tools/dbus-session.sh119
-rw-r--r--tests/tools/eds.sh35
-rwxr-xr-xtests/tools/execute-test.sh30
-rw-r--r--tests/tools/tracker.sh34
-rwxr-xr-xtests/tools/with-session-bus-eds.sh49
-rwxr-xr-xtests/tools/with-session-bus-tracker.sh48
-rwxr-xr-xtests/tools/with-session-bus.sh42
-rw-r--r--tests/tracker/Makefile.am11
72 files changed, 5729 insertions, 1706 deletions
diff --git a/HACKING b/HACKING
index 4aa83a9a..71e7d5ae 100644
--- a/HACKING
+++ b/HACKING
@@ -155,8 +155,9 @@ Then use gdb as normal.
To run a single test:
make -C tests/<dir> check TESTS=<test name>
-To run a single test with debugging output:
- make -C tests/<dir> check TESTS=<test name> CHECK_VERBOSE=1
+Thanks to automake’s parallel test harness, the output from all tests is logged
+automatically to <test name>.log, so no additional options need to be provided
+to force verbose output.
If a test needs to be run through Valgrind for memory debugging, use:
make -C tests/<dir> check TESTS=<test name> FOLKS_TEST_VALGRIND=1
diff --git a/NEWS b/NEWS
index ff1969fb..78fcb22d 100644
--- a/NEWS
+++ b/NEWS
@@ -14,11 +14,15 @@ Bugs fixed:
• Bug 723054 - edsf-persona.vala:1666.21-1666.79: error: Reference transfer
not supported for this expression
• Bug 723540 — standalone-individuals test failing with master
+ • Bug 724339 — vala.m4: don't keep generated files in git
+ • Bug 724809 — Fail to unset contact favorite
+ • Bug 722892 — Linking personas on Dummy backend does not work
API changes:
• Add Individual.display_name
• Add StructuredName.to_string_with_format()
• Add libfolks-dummy.la and all its symbols
+ • Add IndividualAggregator.backend_store
Overview of changes from libfolks 0.9.5 to libfolks 0.9.6
=========================================================
diff --git a/autogen.sh b/autogen.sh
index b3b63b11..a38c8cb8 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -1,19 +1,6 @@
#!/bin/sh
set -e
-if test -n "$AUTOMAKE"; then
- : # don't override an explicit user request
-elif automake-1.11 --version >/dev/null 2>/dev/null && \
- aclocal-1.11 --version >/dev/null 2>/dev/null; then
- # If we have automake-1.11, use it. This is the oldest version (=> least
- # likely to introduce undeclared dependencies) that will give us
- # --enable-silent-rules support.
- AUTOMAKE=automake-1.11
- export AUTOMAKE
- ACLOCAL=aclocal-1.11
- export ACLOCAL
-fi
-
autoreconf -i -f
intltoolize --force --copy --automake
diff --git a/backends/bluez/Makefile.am b/backends/bluez/Makefile.am
index 9cae3823..f644687a 100644
--- a/backends/bluez/Makefile.am
+++ b/backends/bluez/Makefile.am
@@ -7,6 +7,7 @@ backend_LTLIBRARIES = bluez.la
bluez_la_VALAFLAGS = \
$(backend_valaflags) \
--pkg libebook-1.2 \
+ --pkg folks-generics \
$(NULL)
bluez_la_SOURCES = \
diff --git a/backends/bluez/bluez-backend-factory.vala b/backends/bluez/bluez-backend-factory.vala
index 061db6fa..22ef9a51 100644
--- a/backends/bluez/bluez-backend-factory.vala
+++ b/backends/bluez/bluez-backend-factory.vala
@@ -26,48 +26,25 @@
*/
using Folks;
-using Folks.Backends.BlueZ;
-
-private BackendFactory _backend_factory = null;
/**
* The backend module entry point.
*
- * @param backend_store the {@link BackendStore} to use in this factory.
- *
+ * @backend_store a store to add the BlueZ backends to
* @since 0.9.6
*/
public void module_init (BackendStore backend_store)
{
- _backend_factory = new BackendFactory (backend_store);
+ backend_store.add_backend (new Folks.Backends.BlueZ.Backend ());
}
/**
* The backend module exit point.
*
- * @param backend_store the {@link BackendStore} to use in this factory.
- *
+ * @param backend_store the store to remove the backends from
* @since 0.9.6
*/
public void module_finalize (BackendStore backend_store)
{
- _backend_factory = null;
-}
-
-/**
- * A backend factory to create a single {@link Backend}.
- *
- * @since 0.9.6
- */
-public class Folks.Backends.BlueZ.BackendFactory : Object
-{
- /**
- * {@inheritDoc}
- *
- * @since 0.9.6
- */
- public BackendFactory (BackendStore backend_store)
- {
- backend_store.add_backend (new Backend ());
- }
+ /* FIXME: No way to remove backends from the store. */
}
diff --git a/backends/bluez/bluez-backend.vala b/backends/bluez/bluez-backend.vala
index 9032c435..72f7243f 100644
--- a/backends/bluez/bluez-backend.vala
+++ b/backends/bluez/bluez-backend.vala
@@ -170,7 +170,7 @@ public class Folks.Backends.BlueZ.Backend : Folks.Backend
if (!this._persona_stores.has_key (store.id))
return;
- this._remove_persona_store ((!) _store);
+ this._remove_persona_store ((!) _store, true, true);
}
/**
@@ -376,6 +376,10 @@ public class Folks.Backends.BlueZ.Backend : Folks.Backend
PersonaStore store =
new BlueZ.PersonaStore (device, path, this._obex_client);
+ /* Set the initial properties. */
+ store.set_is_trusted (device.trusted);
+ store.set_alias (device.alias);
+
this._watched_devices[path] = store;
this._persona_stores.set (store.id, store);
@@ -384,7 +388,8 @@ public class Folks.Backends.BlueZ.Backend : Folks.Backend
this.notify_property ("persona-stores");
}
- private void _remove_persona_store (PersonaStore store)
+ private void _remove_persona_store (PersonaStore store,
+ bool remove_from_persona_stores, bool remove_from_watched_devices)
{
store.removed.disconnect (this._persona_store_removed_cb);
@@ -394,8 +399,10 @@ public class Folks.Backends.BlueZ.Backend : Folks.Backend
this.persona_store_removed (store);
- this._persona_stores.unset (store.id);
- this._watched_devices.unset (store.object_path);
+ if (remove_from_persona_stores == true)
+ this._persona_stores.unset (store.id);
+ if (remove_from_watched_devices == true)
+ this._watched_devices.unset (store.object_path);
this.notify_property ("persona-stores");
}
@@ -514,7 +521,7 @@ public class Folks.Backends.BlueZ.Backend : Folks.Backend
if (this._watched_devices.unset (path, out store) == true)
{
debug ("Device ‘%s’ removed", path);
- this._remove_persona_store (store);
+ this._remove_persona_store (store, true, false);
}
}
@@ -679,11 +686,13 @@ public class Folks.Backends.BlueZ.Backend : Folks.Backend
this.freeze_notify ();
- foreach (var persona_store in this._persona_stores.values)
- this._remove_persona_store (persona_store);
+ var iter = this._persona_stores.map_iterator ();
+ while (iter.next () == true)
+ {
+ this._remove_persona_store (iter.get_value (), false, true);
+ iter.unset ();
+ }
- this._watched_devices.clear ();
- this._persona_stores.clear ();
this.notify_property ("persona-stores");
this._is_quiescent = false;
@@ -702,6 +711,6 @@ public class Folks.Backends.BlueZ.Backend : Folks.Backend
private void _persona_store_removed_cb (Folks.PersonaStore store)
{
- this._remove_persona_store ((BlueZ.PersonaStore) store);
+ this._remove_persona_store ((BlueZ.PersonaStore) store, true, true);
}
}
diff --git a/backends/bluez/bluez-persona-store.vala b/backends/bluez/bluez-persona-store.vala
index 6ff9f27c..73262187 100644
--- a/backends/bluez/bluez-persona-store.vala
+++ b/backends/bluez/bluez-persona-store.vala
@@ -198,6 +198,8 @@ public class Folks.Backends.BlueZ.PersonaStore : Folks.PersonaStore
*/
public new string display_name
{
+ /* FIXME: Folks.display_name should be abstract, and this should be
+ * override. */
get { return this._display_name; }
construct { this._display_name = value; }
}
@@ -274,6 +276,8 @@ public class Folks.Backends.BlueZ.PersonaStore : Folks.PersonaStore
var removed_personas = new HashSet<Persona> ();
var photos_up_to_date = this._photos_up_to_date;
+ debug ("Parsing contacts from file ‘%s’.", file.get_path ());
+
/* Start with all personas being marked as removed, and then eliminate the
* ones which are found in the vCard. */
removed_personas.add_all (this._personas.values);
@@ -284,6 +288,7 @@ public class Folks.Backends.BlueZ.PersonaStore : Folks.PersonaStore
uint i = 0;
string? line = null;
StringBuilder vcard = new StringBuilder ();
+ var vcard_without_photo = new StringBuilder ();
/* For each vCard in the file create or update a Persona. */
while ((line = yield dis.read_line_async ()) != null)
@@ -294,6 +299,13 @@ public class Folks.Backends.BlueZ.PersonaStore : Folks.PersonaStore
vcard.append (line);
vcard.append_c ('\n');
+
+ if (!line.has_prefix ("PHOTO:") && !line.has_prefix ("PHOTO;"))
+ {
+ vcard_without_photo.append (line);
+ vcard_without_photo.append_c ('\n');
+ }
+
if (line.strip () == "END:VCARD")
{
var card = new E.VCard.from_string (vcard.str);
@@ -311,7 +323,12 @@ public class Folks.Backends.BlueZ.PersonaStore : Folks.PersonaStore
* checksum of the vCard data itself. This means that whenever
* a contact’s properties change in the vCard its IID will
* change and hence the persona will be removed and re-added,
- * but without stable UIDs this is unavoidable. */
+ * but without stable UIDs this is unavoidable.
+ *
+ * Note that the checksum is always calculated from the vCard
+ * data *without* the photo. This hopefully ensures that IIDs
+ * from queries which do and do not include photos will
+ * match. */
var attribute = card.get_attribute ("UID");
if (attribute != null)
{
@@ -323,7 +340,7 @@ public class Folks.Backends.BlueZ.PersonaStore : Folks.PersonaStore
/* Fallback. */
iid =
Checksum.compute_for_string (ChecksumType.SHA1,
- vcard.str);
+ vcard_without_photo.str);
iid_is_checksum = true;
}
@@ -338,10 +355,11 @@ public class Folks.Backends.BlueZ.PersonaStore : Folks.PersonaStore
else
{
/* If the IID is a checksum and we found the persona in
- * the store, that means their properties havent’t
+ * the store, that means their properties haven’t
* changed, so as an optimisation, don’t bother updating
* the Persona from the vCard in that case. */
- if (iid_is_checksum == false)
+ if (iid_is_checksum == false ||
+ vcard_without_photo.len != vcard.len)
{
/* Note: This updates persona’s state, which could be
* left updated if we later throw an error. */
@@ -355,6 +373,7 @@ public class Folks.Backends.BlueZ.PersonaStore : Folks.PersonaStore
i++;
vcard.erase ();
+ vcard_without_photo.erase ();
}
}
}
@@ -369,6 +388,10 @@ public class Folks.Backends.BlueZ.PersonaStore : Folks.PersonaStore
/* Now that all the I/O is done and no more errors can be thrown, update
* the store’s internal state. */
+ debug ("Finished parsing personas; now updating store state with %u " +
+ "added personas and %u removed personas.", added_personas.size,
+ removed_personas.size);
+
foreach (var p in added_personas)
this._personas.set (p.iid, p);
foreach (var p in removed_personas)
@@ -516,6 +539,10 @@ public class Folks.Backends.BlueZ.PersonaStore : Folks.PersonaStore
}
catch (IOError ie)
{
+ /* Ignore errors from closing or cancelling. */
+ if (ie is IOError.CLOSED || ie is IOError.CANCELLED)
+ return;
+
warning ("Couldn’t remove OBEX session ‘%s’: %s",
session_path, ie.message);
}
@@ -568,6 +595,10 @@ public class Folks.Backends.BlueZ.PersonaStore : Folks.PersonaStore
ulong signal_id;
ulong cancellable_id = 0;
+ /* Find the initial status, if it’s already been set. Otherwise it’ll
+ * be null. */
+ transfer_status = transfer.status;
+
/* Set up the cancellable. */
if (cancellable != null)
{
@@ -624,11 +655,24 @@ public class Folks.Backends.BlueZ.PersonaStore : Folks.PersonaStore
/* Process the results: either success or error. */
if (transfer_status == "complete")
{
- string filename = transfer.filename;
- var file = File.new_for_path (filename);
+ string? filename = transfer.filename;
+ if (filename == null)
+ {
+ /* The Filename property is optional, so bail if it’s not
+ * available for whatever reason. */
+ throw new PersonaStoreError.STORE_OFFLINE (
+ /* Translators: the first parameter is the name of the
+ * failed transfer, and the second is a Bluetooth device
+ * alias. */
+ _("Error during transfer of the address book ‘%s’ from " +
+ "Bluetooth device ‘%s’."),
+ transfer.name, this._display_name);
+ }
+
+ var file = File.new_for_path ((!) filename);
debug ("vCard’s filename for device ‘%s’ (%s): %s",
- this._display_name, this.id, filename);
+ this._display_name, this.id, (!) filename);
yield this._update_contacts_from_file (file);
}
@@ -759,9 +803,12 @@ public class Folks.Backends.BlueZ.PersonaStore : Folks.PersonaStore
phonebook_filter.insert ("Format", "Vcard30");
if (download_photos == true)
{
- /* Download only the photo (and UID, if available). */
+ /* Download everything including the photo. */
phonebook_filter.insert ("Fields",
- new Variant.strv ({ "UID", "PHOTO" }));
+ new Variant.strv ({
+ "UID", "N", "FN", "NICKNAME", "TEL", "URL", "EMAIL",
+ "PHOTO"
+ }));
}
else
{
@@ -890,7 +937,8 @@ public class Folks.Backends.BlueZ.PersonaStore : Folks.PersonaStore
PersonaStore._MAX_CONSECUTIVE_FAILURES)
return;
- /* Calculate the timeout. */
+ /* Calculate the timeout (in milliseconds). If no divisor is applied, the
+ * timeout should always be a whole number of seconds. */
var timeout =
uint.min (PersonaStore._TIMEOUT_MIN +
(uint) Math.pow (PersonaStore._TIMEOUT_BASE,
@@ -898,9 +946,23 @@ public class Folks.Backends.BlueZ.PersonaStore : Folks.PersonaStore
PersonaStore._TIMEOUT_MAX);
this._update_contacts_n++;
+ timeout *= 1000; /* convert from seconds to milliseconds */
+
+ /* Allow the timeout to be tweaked for testing. */
+ var divisor_str =
+ Environment.get_variable ("FOLKS_BLUEZ_TIMEOUT_DIVISOR");
+ if (divisor_str != null)
+ {
+ uint64 divisor;
+ if (uint64.try_parse (divisor_str, out divisor) == true)
+ timeout /= (uint) divisor;
+ }
+
/* Schedule the update. */
- this._update_contacts_id = Timeout.add_seconds (timeout, () =>
+ SourceFunc fn = () =>
{
+ debug ("Scheduled update firing for BlueZ store ‘%s’.", this.id);
+
/* Acknowledge the source has fired. */
this._update_contacts_id = 0;
@@ -916,13 +978,33 @@ public class Folks.Backends.BlueZ.PersonaStore : Folks.PersonaStore
if (e4 is IOError.CANCELLED)
return;
- warning ("Error updating persona store from BlueZ: %s",
- e4.message);
+ /* Don't warn about offline stores. */
+ if (e4 is PersonaStoreError.STORE_OFFLINE)
+ {
+ debug ("Not updating persona store from BlueZ due to " +
+ "store being offline: %s", e4.message);
+ }
+ else
+ {
+ warning ("Error updating persona store from BlueZ: %s",
+ e4.message);
+ }
}
});
return false;
- });
+ };
+
+ if (timeout % 1000 == 0)
+ {
+ this._update_contacts_id =
+ Timeout.add_seconds (timeout / 1000, (owned) fn);
+ }
+ else
+ {
+ this._update_contacts_id =
+ Timeout.add (timeout, (owned) fn);
+ }
}
/**
diff --git a/backends/bluez/bluez-persona.vala b/backends/bluez/bluez-persona.vala
index b93eb469..ac6e2d5c 100644
--- a/backends/bluez/bluez-persona.vala
+++ b/backends/bluez/bluez-persona.vala
@@ -41,17 +41,6 @@ public class Folks.Backends.BlueZ.Persona : Folks.Persona,
PhoneDetails,
UrlDetails
{
- private StructuredName? _structured_name = null;
- private string _full_name = "";
- private string _nickname = "";
- private Set<UrlFieldDetails>? _urls = null;
- private Set<UrlFieldDetails>? _urls_ro = null;
- private LoadableIcon? _avatar = null;
- private HashSet<PhoneFieldDetails> _phone_numbers;
- private Set<PhoneFieldDetails> _phone_numbers_ro;
- private HashSet<EmailFieldDetails> _email_addresses;
- private Set<EmailFieldDetails> _email_addresses_ro;
-
private const string[] _linkable_properties =
{
"phone-numbers",
@@ -69,6 +58,9 @@ public class Folks.Backends.BlueZ.Persona : Folks.Persona,
get { return BlueZ.Persona._linkable_properties; }
}
+ private SmallSet<UrlFieldDetails>? _urls = null;
+ private Set<UrlFieldDetails> _urls_ro;
+
/**
* {@inheritDoc}
*
@@ -81,6 +73,8 @@ public class Folks.Backends.BlueZ.Persona : Folks.Persona,
set { this.change_urls.begin (value); } /* not writeable */
}
+ private LoadableIcon? _avatar = null;
+
/**
* {@inheritDoc}
*
@@ -103,6 +97,9 @@ public class Folks.Backends.BlueZ.Persona : Folks.Persona,
get { return BlueZ.Persona._writeable_properties; }
}
+ private SmallSet<PhoneFieldDetails>? _phone_numbers = null;
+ private Set<PhoneFieldDetails> _phone_numbers_ro;
+
/**
* {@inheritDoc}
*
@@ -115,6 +112,8 @@ public class Folks.Backends.BlueZ.Persona : Folks.Persona,
set { this.change_phone_numbers.begin (value); } /* not writeable */
}
+ private StructuredName? _structured_name = null;
+
/**
* {@inheritDoc}
*
@@ -127,6 +126,8 @@ public class Folks.Backends.BlueZ.Persona : Folks.Persona,
set { this.change_structured_name.begin (value); } /* not writeable */
}
+ private string _full_name = "";
+
/**
* {@inheritDoc}
*
@@ -139,6 +140,8 @@ public class Folks.Backends.BlueZ.Persona : Folks.Persona,
set { this.change_full_name.begin (value); } /* not writeable */
}
+ private string _nickname = "";
+
/**
* {@inheritDoc}
*
@@ -151,6 +154,9 @@ public class Folks.Backends.BlueZ.Persona : Folks.Persona,
set { this.change_nickname.begin (value); } /* not writeable */
}
+ private SmallSet<EmailFieldDetails>? _email_addresses = null;
+ private Set<EmailFieldDetails> _email_addresses_ro;
+
/**
* {@inheritDoc}
*
@@ -197,16 +203,35 @@ public class Folks.Backends.BlueZ.Persona : Folks.Persona,
{
debug ("Adding BlueZ Persona '%s' (IID '%s')", this.uid, this.iid);
- this._phone_numbers = new HashSet<PhoneFieldDetails> ();
+ this._phone_numbers = new SmallSet<PhoneFieldDetails> (
+ AbstractFieldDetails<string>.hash_static,
+ AbstractFieldDetails<string>.equal_static);
this._phone_numbers_ro = this._phone_numbers.read_only_view;
-
- this._email_addresses = new HashSet<EmailFieldDetails> ();
+ this._email_addresses = new SmallSet<EmailFieldDetails> (
+ AbstractFieldDetails<string>.hash_static,
+ AbstractFieldDetails<string>.equal_static);
this._email_addresses_ro = this._email_addresses.read_only_view;
-
- this._urls = new HashSet<UrlFieldDetails> ();
+ this._urls = new SmallSet<UrlFieldDetails> (
+ AbstractFieldDetails<string>.hash_static,
+ AbstractFieldDetails<string>.equal_static);
this._urls_ro = this._urls.read_only_view;
}
+ private void _update_params (AbstractFieldDetails details,
+ E.VCardAttribute attr)
+ {
+ foreach (unowned E.VCardAttributeParam param in attr.get_params ())
+ {
+ /* EVCard handles parameter names and values entirely
+ * case-insensitively, so we’ll do the same. */
+ foreach (unowned string param_value in param.get_values ())
+ {
+ details.add_parameter (param.get_name ().down (),
+ param_value.down ());
+ }
+ }
+ }
+
/**
* Update the Persona’s properties from a vCard.
*
@@ -222,69 +247,136 @@ public class Folks.Backends.BlueZ.Persona : Folks.Persona,
{
var properties_changed = false;
- this.freeze_notify ();
+ /* Somewhere to store the new property values. */
+ var new_phone_numbers = new SmallSet<PhoneFieldDetails> (
+ AbstractFieldDetails<string>.hash_static,
+ AbstractFieldDetails<string>.equal_static);
+ var new_uris = new SmallSet<UrlFieldDetails> (
+ AbstractFieldDetails<string>.hash_static,
+ AbstractFieldDetails<string>.equal_static);
+ var new_email_addresses = new SmallSet<EmailFieldDetails> (
+ AbstractFieldDetails<string>.hash_static,
+ AbstractFieldDetails<string>.equal_static);
+ BytesIcon? new_avatar = null;
+ var new_full_name = "";
+ var new_nickname = "";
+ StructuredName? new_structured_name = null;
- /* Phone numbers. */
- var attribute = card.get_attribute ("TEL");
- var new_phone_numbers = new HashSet<PhoneFieldDetails> ();
+ /* Parse the attributes by iterating over the vCard’s attribute list once
+ * only. Convenience functions like E.VCard.get_attribute() cause multiple
+ * iterations over the list. */
+ unowned GLib.List<unowned E.VCardAttribute> attrs =
+ card.get_attributes ();
- if (attribute != null)
+ foreach (var attr in attrs)
{
- unowned GLib.List<unowned StringBuilder> vals =
- attribute.get_values_decoded ();
- foreach (unowned StringBuilder v in vals)
- new_phone_numbers.add (new PhoneFieldDetails (v.str));
- }
+ unowned string attr_name = attr.get_name ();
- if (!Folks.Internal.equal_sets<PhoneFieldDetails> (this._phone_numbers,
- new_phone_numbers))
- {
- this._phone_numbers = new_phone_numbers;
- this._phone_numbers_ro = new_phone_numbers.read_only_view;
- this.notify_property ("phone-numbers");
- properties_changed = true;
- }
+ if (attr_name == "TEL")
+ {
+ var val = attr.get_value ();
+ if (val == null || (!) val == "")
+ continue;
- /* Full name. */
- attribute = card.get_attribute ("FN");
- var new_full_name = "";
+ var new_field_details = new PhoneFieldDetails ((!) val);
+ this._update_params (new_field_details, attr);
+ new_phone_numbers.add (new_field_details);
+ }
+ else if (attr_name == "URL")
+ {
+ var val = attr.get_value ();
+ if (val == null || (!) val == "")
+ continue;
- if (attribute != null)
- new_full_name = attribute.get_value_decoded ().str;
+ var new_field_details = new UrlFieldDetails ((!) val);
+ this._update_params (new_field_details, attr);
+ new_uris.add (new_field_details);
+ }
+ else if (attr_name == "EMAIL")
+ {
+ var val = attr.get_value ();
+ if (val == null || (!) val == "")
+ continue;
- if (this._full_name != new_full_name)
- {
- this._full_name = new_full_name;
- this.notify_property ("full-name");
- properties_changed = true;
+ var new_field_details = new EmailFieldDetails ((!) val);
+ this._update_params (new_field_details, attr);
+ new_email_addresses.add (new_field_details);
+ }
+ else if (attr_name == "PHOTO")
+ {
+ var encoded_data = (string) attr.get_value ().data;
+ var bytes = new Bytes (Base64.decode (encoded_data));
+ new_avatar = new BytesIcon (bytes);
+ }
+ else if (attr_name == "FN")
+ new_full_name = attr.get_value ();
+ else if (attr_name == "NICKNAME")
+ new_nickname = attr.get_value ();
+ else if (attr_name == "N")
+ {
+ unowned GLib.List<unowned string> values = attr.get_values ();
+ unowned string? family_name = null, given_name = null,
+ additional_names = null, prefixes = null, suffixes = null;
+
+ if (values != null)
+ {
+ family_name = values.data;
+ values = values.next;
+ }
+ if (values != null)
+ {
+ given_name = values.data;
+ values = values.next;
+ }
+ if (values != null)
+ {
+ additional_names = values.data;
+ values = values.next;
+ }
+ if (values != null)
+ {
+ prefixes = values.data;
+ values = values.next;
+ }
+ if (values != null)
+ {
+ suffixes = values.data;
+ values = values.next;
+ }
+
+ if (suffixes == null || values != null)
+ {
+ debug ("Expected 5 components in N attribute of vCard, " +
+ "but got %s.", (suffixes == null) ? "fewer" : "more");
+ }
+
+ new_structured_name =
+ new StructuredName (family_name, given_name, additional_names,
+ prefixes, suffixes);
+ }
+ else if (attr_name != "VERSION" && attr_name != "UID")
+ {
+ /* Unknown attribute. */
+ warning ("Unknown attribute ‘%s’ in vCard for persona %s.",
+ attr_name, this.uid);
+ }
}
- /* Nickname. */
- attribute = card.get_attribute ("NICKNAME");
- var new_nickname = "";
-
- if (attribute != null)
- new_nickname = attribute.get_value_decoded ().str;
+ /* Now test the new property values to see if they’ve changed; if so, emit
+ * property change notifications. */
+ this.freeze_notify ();
- if (this._nickname != new_nickname)
+ /* Phone numbers. */
+ if (!Folks.Internal.equal_sets<PhoneFieldDetails> (this._phone_numbers,
+ new_phone_numbers))
{
- this._nickname = new_nickname;
- this.notify_property ("nickname");
+ this._phone_numbers = new_phone_numbers;
+ this._phone_numbers_ro = new_phone_numbers.read_only_view;
+ this.notify_property ("phone-numbers");
properties_changed = true;
}
/* URIs. */
- attribute = card.get_attribute ("URL");
- var new_uris = new HashSet<UrlFieldDetails> ();
-
- if (attribute != null)
- {
- unowned GLib.List<unowned StringBuilder> vals =
- attribute.get_values_decoded ();
- foreach (unowned StringBuilder v in vals)
- new_uris.add (new UrlFieldDetails (v.str));
- }
-
if (!Folks.Internal.equal_sets<UrlFieldDetails> (this._urls, new_uris))
{
this._urls = new_uris;
@@ -293,56 +385,7 @@ public class Folks.Backends.BlueZ.Persona : Folks.Persona,
properties_changed = true;
}
- /* Structured name. */
- attribute = card.get_attribute ("N");
- StructuredName? new_structured_name = null;
-
- if (attribute != null)
- {
- string[] components = { "", "", "", "", "" };
- unowned GLib.List<unowned StringBuilder> values =
- attribute.get_values_decoded ();
-
- uint i = 0;
- foreach (unowned StringBuilder b in values)
- {
- if (i >= components.length)
- break;
-
- components[i++] = b.str;
- }
-
- this._structured_name = new StructuredName (components[0],
- components[1], components[2], components[3], components[4]);
-
- if (i != 5)
- {
- debug ("Expected 5 components in N value of vCard, but got %u.",
- i);
- }
- }
-
- if ((new_structured_name == null) != (this._structured_name == null) ||
- (new_structured_name != null && this._structured_name != null &&
- !new_structured_name.equal (this._structured_name)))
- {
- this._structured_name = new_structured_name;
- this.notify_property ("structured-name");
- properties_changed = true;
- }
-
/* E-mail addresses. */
- attribute = card.get_attribute ("EMAIL");
- var new_email_addresses = new HashSet<EmailFieldDetails> ();
-
- if (attribute != null)
- {
- unowned GLib.List<unowned StringBuilder> vals =
- attribute.get_values_decoded ();
- foreach (unowned StringBuilder v in vals)
- new_email_addresses.add (new EmailFieldDetails (v.str));
- }
-
if (!Folks.Internal.equal_sets<EmailFieldDetails> (this._email_addresses,
new_email_addresses))
{
@@ -353,16 +396,6 @@ public class Folks.Backends.BlueZ.Persona : Folks.Persona,
}
/* Photo. */
- attribute = card.get_attribute ("PHOTO");
- BytesIcon? new_avatar = null;
-
- if (attribute != null)
- {
- var encoded_data = (string) attribute.get_value ().data;
- var bytes = new Bytes (Base64.decode (encoded_data));
- new_avatar = new BytesIcon (bytes);
- }
-
if ((new_avatar == null) != (this._avatar == null) ||
(new_avatar != null && this._avatar != null &&
!new_avatar.equal (this._avatar)))
@@ -372,6 +405,32 @@ public class Folks.Backends.BlueZ.Persona : Folks.Persona,
properties_changed = true;
}
+ /* Full name. */
+ if (this._full_name != new_full_name)
+ {
+ this._full_name = new_full_name;
+ this.notify_property ("full-name");
+ properties_changed = true;
+ }
+
+ /* Nickname. */
+ if (this._nickname != new_nickname)
+ {
+ this._nickname = new_nickname;
+ this.notify_property ("nickname");
+ properties_changed = true;
+ }
+
+ /* Structured name. */
+ if ((new_structured_name == null) != (this._structured_name == null) ||
+ (new_structured_name != null && this._structured_name != null &&
+ !new_structured_name.equal (this._structured_name)))
+ {
+ this._structured_name = new_structured_name;
+ this.notify_property ("structured-name");
+ properties_changed = true;
+ }
+
this.thaw_notify ();
return properties_changed;
diff --git a/backends/dummy/lib/dummy-full-persona.vala b/backends/dummy/lib/dummy-full-persona.vala
index 8330abb6..f998664a 100644
--- a/backends/dummy/lib/dummy-full-persona.vala
+++ b/backends/dummy/lib/dummy-full-persona.vala
@@ -72,6 +72,16 @@ public class FolksDummy.FullPersona : FolksDummy.Persona,
PostalAddressDetails,
WebServiceDetails
{
+ private const string[] _default_linkable_properties =
+ {
+ "im-addresses",
+ "email-addresses",
+ "local-ids",
+ "web-service-addresses",
+ null /* FIXME: https://bugzilla.gnome.org/show_bug.cgi?id=682698 */
+ };
+
+
/**
* Create a new ‘full’ persona.
*
@@ -88,7 +98,8 @@ public class FolksDummy.FullPersona : FolksDummy.Persona,
* @since UNRELEASED
*/
public FullPersona (PersonaStore store, string contact_id,
- bool is_user = false, string[] linkable_properties = {})
+ bool is_user = false,
+ string[] linkable_properties = {})
{
base (store, contact_id, is_user, linkable_properties);
}
@@ -104,6 +115,8 @@ public class FolksDummy.FullPersona : FolksDummy.Persona,
this._groups_ro = this._groups.read_only_view;
this._roles_ro = this._roles.read_only_view;
this._anti_links_ro = this._anti_links.read_only_view;
+ this.update_linkable_properties (
+ FullPersona._default_linkable_properties);
}
private HashMultiMap<string, WebServiceFieldDetails> _web_service_addresses =
diff --git a/backends/dummy/lib/dummy-persona.vala b/backends/dummy/lib/dummy-persona.vala
index a0d8cbdb..56679d20 100644
--- a/backends/dummy/lib/dummy-persona.vala
+++ b/backends/dummy/lib/dummy-persona.vala
@@ -96,8 +96,8 @@ public class FolksDummy.Persona : Folks.Persona
*
* @since UNRELEASED
*/
- public Persona (PersonaStore store, string contact_id, bool is_user = false,
- string[] linkable_properties = {})
+ public Persona (PersonaStore store, string contact_id,
+ bool is_user = false, string[] linkable_properties = {})
{
var uid = Folks.Persona.build_uid (BACKEND_NAME, store.id, contact_id);
var iid = store.id + ":" + contact_id;
@@ -234,6 +234,32 @@ public class FolksDummy.Persona : Folks.Persona
}
/**
+ * Update the persona’s set of linkable properties.
+ *
+ * Update the {@link Folks.Persona.linkable_properties} property to contain
+ * the given ``linkable_properties``.
+ *
+ * @param linkable_properties new set of linkable property names, in lower
+ * case, hyphenated form
+ * @since UNRELEASED
+ */
+ public void update_linkable_properties (string[] linkable_properties)
+ {
+ var new_linkable_properties = new SmallSet<string> ();
+ new_linkable_properties.add_all_array (linkable_properties);
+
+ var old_linkable_properties = new SmallSet<string> ();
+ old_linkable_properties.add_all_array (this._linkable_properties);
+
+ if (!Folks.Internal.equal_sets<string> (old_linkable_properties,
+ new_linkable_properties))
+ {
+ this._linkable_properties = linkable_properties;
+ this.notify_property ("linkable-properties");
+ }
+ }
+
+ /**
* Delay between property changes and notifications.
*
* This sets an optional delay between client code requesting a property
diff --git a/backends/eds/eds-backend.vala b/backends/eds/eds-backend.vala
index 90855f2d..7bdb1a57 100644
--- a/backends/eds/eds-backend.vala
+++ b/backends/eds/eds-backend.vala
@@ -133,11 +133,11 @@ public class Folks.Backends.Eds.Backend : Folks.Backend
}
}
- var iter = this._persona_stores.values.iterator ();
+ var iter = this._persona_stores.map_iterator ();
while (iter.next ())
{
- var store = iter.get ();
+ var store = iter.get_value ();
if (!storeids.contains (store.id))
{
@@ -249,10 +249,10 @@ public class Folks.Backends.Eds.Backend : Folks.Backend
this._prepare_pending = true;
this.freeze_notify ();
- var iter = this._persona_stores.values.iterator ();
+ var iter = this._persona_stores.map_iterator ();
while (iter.next ())
- this._remove_address_book (iter.get (), true, iter);
+ this._remove_address_book (iter.get_value (), true, iter);
this._ab_sources.source_added.disconnect (this._ab_source_list_changed_cb);
this._ab_sources.source_enabled.disconnect (this._ab_source_list_changed_cb);
@@ -345,14 +345,14 @@ public class Folks.Backends.Eds.Backend : Folks.Backend
private void _remove_address_book (Folks.PersonaStore store,
bool notify = true,
- Iterator<Folks.PersonaStore>? iter = null)
+ MapIterator<string, Folks.PersonaStore>? iter = null)
{
debug ("Removing address book '%s'.", store.id);
if (iter != null)
{
- assert (store == iter.get ());
- iter.remove ();
+ assert (store == iter.get_value ());
+ iter.unset ();
}
else
{
diff --git a/backends/eds/lib/edsf-persona-store.vala b/backends/eds/lib/edsf-persona-store.vala
index 0c6b9c15..1fc3425a 100644
--- a/backends/eds/lib/edsf-persona-store.vala
+++ b/backends/eds/lib/edsf-persona-store.vala
@@ -313,8 +313,9 @@ public class Edsf.PersonaStore : Folks.PersonaStore
public PersonaStore.with_source_registry (E.SourceRegistry r, E.Source s)
{
string eds_uid = s.get_uid ();
+ string eds_name = s.get_display_name ();
Object (id: eds_uid,
- display_name: eds_uid,
+ display_name: eds_name,
source: s);
this._source_registry = r;
@@ -366,7 +367,8 @@ public class Edsf.PersonaStore : Folks.PersonaStore
}
catch (GLib.Error e)
{
- GLib.warning ("~PersonaStore: %s\n", e.message);
+ if (!(e is IOError.CLOSED))
+ GLib.warning ("~PersonaStore: %s\n", e.message);
}
}
@@ -1227,6 +1229,16 @@ public class Edsf.PersonaStore : Folks.PersonaStore
* if _addressbook is null. */
assert (this._addressbook != null);
+ var debug_obj = Debug.dup ();
+ if (debug_obj.debug_output_enabled == true)
+ {
+ debug ("Committing modified property ‘%s’ to persona %p (UID: %s).",
+ property_name, persona, persona.uid);
+
+ debug ("Modified vCard: %s",
+ persona.contact.to_string (E.VCardFormat.@30));
+ }
+
var contact = persona.contact;
ulong signal_id = 0;
@@ -1272,10 +1284,15 @@ public class Edsf.PersonaStore : Folks.PersonaStore
* they can only be modified from the main loop. */
if (received_notification == false)
{
+ debug ("Yielding.");
has_yielded = true;
yield;
}
+ debug ("Finished: received_notification = %s, has_yielded = %s",
+ received_notification ? "yes" : "no",
+ has_yielded ? "yes" : "no");
+
/* If we hit the timeout instead of the property notification, throw
* an error. */
if (received_notification == false)
@@ -1309,11 +1326,7 @@ public class Edsf.PersonaStore : Folks.PersonaStore
private void _remove_attribute (E.Contact contact, string attr_name)
{
- unowned VCardAttribute? attr = contact.get_attribute (attr_name);
- if (attr != null)
- {
- contact.remove_attribute ((!) attr);
- }
+ contact.remove_attributes (null, attr_name);
}
internal async void _set_avatar (Edsf.Persona persona, LoadableIcon? avatar)
@@ -2048,14 +2061,14 @@ public class Edsf.PersonaStore : Folks.PersonaStore
private void _set_contact_system_groups (E.Contact contact, Set<string> system_groups)
{
+ var group_ids_str = "X-GOOGLE-SYSTEM-GROUP-IDS";
var vcard = (E.VCard) contact;
- unowned E.VCardAttribute? prev_attr =
- vcard.get_attribute ("X-GOOGLE-SYSTEM-GROUP-IDS");
+ unowned E.VCardAttribute? prev_attr = vcard.get_attribute (group_ids_str);
if (prev_attr != null)
- contact.remove_attribute (prev_attr);
+ contact.remove_attributes (null, group_ids_str);
- E.VCardAttribute new_attr = new E.VCardAttribute ("", "X-GOOGLE-SYSTEM-GROUP-IDS");
+ E.VCardAttribute new_attr = new E.VCardAttribute ("", group_ids_str);
foreach (var group in system_groups)
{
if (group == null || group == "")
diff --git a/backends/eds/lib/edsf-persona.vala b/backends/eds/lib/edsf-persona.vala
index 7a076f18..1dd3c896 100644
--- a/backends/eds/lib/edsf-persona.vala
+++ b/backends/eds/lib/edsf-persona.vala
@@ -119,7 +119,7 @@ public class Edsf.Persona : Folks.Persona,
* and the value ‘TRUE’. This allows clients to detect such fields
* and (for example) ignore them in the UI.
*
- * Since: UNRELEASED
+ * @since UNRELEASED
*/
public static const string folks_field_attribute_name = "X-FOLKS-FIELD";
@@ -1007,7 +1007,6 @@ public class Edsf.Persona : Folks.Persona,
new HashMultiMap<string, WebServiceFieldDetails> (
null, null, AbstractFieldDetails<string>.hash_static,
AbstractFieldDetails<string>.equal_static);
- this._email_addresses_ro = this._email_addresses.read_only_view;
this._groups = new SmallSet<string> ();
this._groups_ro = this._groups.read_only_view;
this._roles = new SmallSet<RoleFieldDetails> (
diff --git a/backends/tracker/lib/trf-persona-store.vala b/backends/tracker/lib/trf-persona-store.vala
index 5d5613ec..dc570d0a 100644
--- a/backends/tracker/lib/trf-persona-store.vala
+++ b/backends/tracker/lib/trf-persona-store.vala
@@ -1134,8 +1134,13 @@ public class Trf.PersonaStore : Folks.PersonaStore
}
catch (GLib.IOError e1)
{
- warning ("Could not connect to D-Bus service: %s",
- e1.message);
+ /* Ignore errors from the bus disappearing. */
+ if (!(e1 is IOError.CLOSED))
+ {
+ warning ("Could not connect to D-Bus service: %s",
+ e1.message);
+ }
+
this.removed ();
throw new PersonaStoreError.INVALID_ARGUMENT (e1.message);
}
diff --git a/check.mk b/check.mk
index 55ebf836..34951c41 100644
--- a/check.mk
+++ b/check.mk
@@ -1,7 +1,6 @@
# taken from gstreamer
# gdb any given test by running make test.gdb
%.gdb: %
- CHECK_VERBOSE=1 \
$(TESTS_ENVIRONMENT) \
$(LIBTOOL) --mode=execute \
gdb $*
diff --git a/configure.ac b/configure.ac
index b25d40ba..03bd4b11 100644
--- a/configure.ac
+++ b/configure.ac
@@ -79,7 +79,7 @@ AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_SRCDIR([Makefile.am])
AC_CONFIG_HEADERS(config.h)
AC_CONFIG_SRCDIR([configure.ac])
-AM_INIT_AUTOMAKE([1.11 dist-xz no-define
+AM_INIT_AUTOMAKE([1.12 dist-xz no-define
no-dist-gzip tar-ustar -Wno-portability color-tests
parallel-tests])
AM_MAINTAINER_MODE([enable])
@@ -339,8 +339,29 @@ AS_IF([test x$enable_ofono_backend = xyes], [
AS_IF([test x$enable_bluez_backend = xyes], [
PKG_CHECK_MODULES([EBOOK], [libebook-1.2 >= $EBOOK_REQUIRED])
+
+ # Dependencies for the BlueZ tests
+ PKG_CHECK_MODULES([GLIB_2_39_2], [glib-2.0 >= 2.39.2],
+ [have_glib_2_39_2=yes], [have_glib_2_39_2=no])
+ AM_PATH_PYTHON([3.0], [have_python=yes], [have_python=no])
+
+ AC_MSG_CHECKING([for python-dbusmock])
+ AS_IF([! $PYTHON -c 'import dbusmock' > /dev/null 2>&1],
+ [have_dbusmock=no], [have_dbusmock=yes])
+ AC_MSG_RESULT([$have_dbusmock])
+
+ AM_PROG_VALAC([0.22.0.45-383d-dirty],
+ [have_valac_0_22_2=yes], [have_valac_0_22_2=no])
])
+# The BlueZ tests are conditional on several bleeding-edge dependencies.
+# FIXME: Remove this once things have stabilised a bit.
+AM_CONDITIONAL([HAVE_BLUEZ_TESTS],
+ [test "x$have_glib_2_39_2" = "xyes" -a \
+ "x$have_python" = "xyes" -a \
+ "x$have_dbusmock" = "xyes" -a \
+ "x$have_valac_0_22_2" = "xyes"])
+
#
# Vala building options -- allows tarball builds without installing Vala
#
@@ -754,6 +775,7 @@ AC_CONFIG_FILES([
docs/Makefile
po/Makefile.in
tests/Makefile
+ tests/bluez/Makefile
tests/data/Makefile
tests/eds/Makefile
tests/folks/Makefile
@@ -764,6 +786,7 @@ AC_CONFIG_FILES([
tests/tracker/Makefile
tests/lib/Makefile
tests/lib/folks-test-uninstalled.pc
+ tests/lib/bluez/Makefile
tests/lib/eds/Makefile
tests/lib/dummy/Makefile
tests/lib/key-file/Makefile
diff --git a/docs/Makefile.am b/docs/Makefile.am
index 205aca03..3092fee8 100644
--- a/docs/Makefile.am
+++ b/docs/Makefile.am
@@ -126,6 +126,7 @@ folks_dummy_doc_deps = \
gee-0.8 \
folks \
folks-internal \
+ folks-generics \
$(NULL)
valadoc_flags_folks_dummy = \
$(valadoc_flags) \
diff --git a/folks/anti-linkable.vala b/folks/anti-linkable.vala
index 93a82c79..0c3657e6 100644
--- a/folks/anti-linkable.vala
+++ b/folks/anti-linkable.vala
@@ -45,6 +45,9 @@ public interface Folks.AntiLinkable : Folks.Persona
* {@link Persona} instance) are permitted, as personas may appear and
* disappear over time.
*
+ * The special UID ``*`` is used as a wildcard to mark the persona as globally
+ * anti-linked. See {@link AntiLinkable.has_global_anti_link}.
+ *
* It is expected, but not guaranteed, that anti-links made between personas
* will be reciprocal. That is, if persona A lists persona B's UID in its
* {@link AntiLinkable.anti_links} set, persona B will typically also list
@@ -93,7 +96,8 @@ public interface Folks.AntiLinkable : Folks.Persona
*/
public bool has_anti_link_with_persona (Persona other_persona)
{
- return (other_persona.uid in this.anti_links);
+ return (this.has_global_anti_link ()) ||
+ (other_persona.uid in this.anti_links);
}
/**
@@ -137,6 +141,9 @@ public interface Folks.AntiLinkable : Folks.Persona
* The UIDs of all personas in ``other_personas`` will be removed from this
* persona's anti-links set and the changes propagated to backends.
*
+ * If the global anti-link is set, this will not have any effect until the
+ * global anti-link is removed.
+ *
* This method is safe to call multiple times concurrently (e.g. begin one
* asynchronous call, then begin another before the first has finished).
*
@@ -156,6 +163,67 @@ public interface Folks.AntiLinkable : Folks.Persona
yield this.change_anti_links (new_anti_links);
}
+
+ /**
+ * Prevent persona from being linked with any other personas
+ *
+ * This function will add a wildcard ``*`` to the set of anti-links, which will
+ * prevent the persona from being linked with any other personas.
+ *
+ * To make the persona linkable again you need to remove the global anti-link
+ *
+ * This method is safe to call multiple times concurrently (e.g. begin one
+ * asynchronous call, then begin another before the first has finished).
+ *
+ * @throws PropertyError if setting the anti-links failed
+ * @since UNRELEASED
+ */
+ public async void add_global_anti_link()
+ throws PropertyError
+ {
+ if (!this.has_global_anti_link())
+ {
+ var new_anti_links = SmallSet.copy (this.anti_links);
+ new_anti_links.add ("*");
+ yield this.change_anti_links (new_anti_links);
+ }
+ }
+
+ /**
+ * Allow persona to be linked with other personas
+ *
+ * This function removes the wildcard ``*`` from the set of anti-links, allowing
+ * the persona to be linked again.
+ *
+ * This method is safe to call multiple times concurrently (e.g. begin one
+ * asynchronous call, then begin another before the first has finished).
+ *
+ * @throws PropertyError if setting the anti-links failed
+ * @since UNRELEASED
+ */
+ public async void remove_global_anti_link()
+ throws PropertyError
+ {
+ if (this.has_global_anti_link())
+ {
+ var new_anti_links = SmallSet.copy (this.anti_links);
+ new_anti_links.remove ("*");
+ yield this.change_anti_links (new_anti_links);
+ }
+ }
+
+ /**
+ * Check if the persona has a global anti link.
+ *
+ * If the persona has global anti link this means that the persona can not be
+ * linked with any other persona.
+ *
+ * @since UNRELEASED
+ */
+ public bool has_global_anti_link()
+ {
+ return (this.anti_links.contains ("*"));
+ }
}
/* vim: filetype=vala textwidth=80 tabstop=2 expandtab: */
diff --git a/folks/backend-store.vala b/folks/backend-store.vala
index 4af4d20f..e2ec2877 100644
--- a/folks/backend-store.vala
+++ b/folks/backend-store.vala
@@ -158,6 +158,16 @@ public class Folks.BackendStore : Object {
~BackendStore ()
{
+ /* Unprepare all existing backends. */
+ var iter = this._prepared_backends.map_iterator ();
+ while (iter.next () == true)
+ {
+ var backend = iter.get_value ();
+ backend.unprepare.begin ();
+ }
+
+ this._prepared_backends.clear ();
+
/* Finalize all the loaded modules that have finalize functions */
foreach (var module in this._modules.values)
{
@@ -169,6 +179,8 @@ public class Folks.BackendStore : Object {
}
}
+ this._modules.clear ();
+
/* Disconnect from the debug handler */
this._debug.print_status.disconnect (this._debug_print_status);
diff --git a/folks/individual-aggregator.vala b/folks/individual-aggregator.vala
index 18151455..06d0f3da 100644
--- a/folks/individual-aggregator.vala
+++ b/folks/individual-aggregator.vala
@@ -217,6 +217,17 @@ public class Folks.IndividualAggregator : Object
get { return this._primary_store; }
}
+ /**
+ * The backend store providing the persona stores for this aggregator.
+ *
+ * @since UNRELEASED
+ */
+ public BackendStore backend_store
+ {
+ get { return this._backend_store; }
+ construct { this._backend_store = value; }
+ }
+
private Map<string, Individual> _individuals;
private Map<string, Individual> _individuals_ro;
@@ -376,8 +387,7 @@ public class Folks.IndividualAggregator : Object
replacement = "IndividualAggregator.dup")]
public IndividualAggregator ()
{
- Object ();
- this._backend_store = BackendStore.dup ();
+ Object (backend_store: BackendStore.dup ());
}
/**
@@ -437,8 +447,7 @@ public class Folks.IndividualAggregator : Object
replacement = "IndividualAggregator.dup_with_backend_store")]
public IndividualAggregator.with_backend_store (BackendStore store)
{
- Object ();
- this._backend_store = store;
+ Object (backend_store: store);
}
construct
@@ -504,8 +513,6 @@ public class Folks.IndividualAggregator : Object
this._linking_enabled = (disable_linking == null ||
disable_linking == "no" || disable_linking == "0");
- this._backend_store = BackendStore.dup ();
-
debug ("Constructing IndividualAggregator %p", this);
}
diff --git a/m4/vala.m4 b/m4/vala.m4
deleted file mode 100644
index 37359488..00000000
--- a/m4/vala.m4
+++ /dev/null
@@ -1,70 +0,0 @@
-dnl vala.m4
-dnl
-dnl Copyright 2010 Marc-Andre Lureau
-dnl
-dnl This library is free software; you can redistribute it and/or
-dnl modify it under the terms of the GNU Lesser General Public
-dnl License as published by the Free Software Foundation; either
-dnl version 2.1 of the License, or (at your option) any later version.
-dnl
-dnl This library is distributed in the hope that it will be useful,
-dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
-dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-dnl Lesser General Public License for more details.
-dnl
-dnl You should have received a copy of the GNU Lesser General Public
-dnl License along with this library; if not, write to the Free Software
-dnl Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-
-# _VALA_CHECK_COMPILE_WITH_ARGS(ARGS, [ACTION-IF-TRUE],
-# [ACTION-IF-FALSE])
-# --------------------------------------
-# Check that Vala compile with ARGS.
-#
-AC_DEFUN([_VALA_CHECK_COMPILE_WITH_ARGS],
-[AC_REQUIRE([AM_PROG_VALAC])[]dnl
-
- cat <<_ACEOF >conftest.vala
-void main(){}
-_ACEOF
-
- AS_IF([vala_error=`$VALAC $1 -q -o conftest$ac_exeext conftest.vala 2>&1`],
- [$2], [$3])
-])
-
-])# _VALA_CHECK_COMPILE_WITH_ARGS
-
-# VALA_CHECK_PACKAGES(PKGS, [ACTION-IF-FOUND],
-# [ACTION-IF-NOT-FOUND])
-# --------------------------------------
-# Check that PKGS Vala bindings are installed and usable.
-#
-AC_DEFUN([VALA_CHECK_PACKAGES],
-[
- ac_save_ifs="$IFS"; unset IFS
- for vala_pkg in $(echo "$1"); do
- vala_pkgs="$vala_pkgs --pkg $vala_pkg"
- vala_bindings="$vala_bindings $vala_pkg"
- done
- IFS="$ac_save_ifs"
- AC_MSG_CHECKING([for $vala_bindings vala bindings])
- _VALA_CHECK_COMPILE_WITH_ARGS([$vala_pkgs],
- [vala_pkg_exists=yes],
- [vala_pkg_exists=no])
-
-AS_IF([test x${vala_pkg_exists} = xno],[
- ifelse([$3], , [AC_MSG_ERROR([]dnl
-[Package requirements were not met: $1
-
-$vala_error
-
-Consider adjusting the XDG_DATA_DIRS environment variable if you
-installed bindings in a non-standard prefix.
-])],
- [AC_MSG_RESULT([no])
-$3])],[
- AC_MSG_RESULT([yes])
- ifelse([$2], , :, [$2])[]dnl
-])
-
-])# VALA_CHECK_PACKAGES
diff --git a/po/da.po b/po/da.po
index 1bfa3ff5..9305f82e 100644
--- a/po/da.po
+++ b/po/da.po
@@ -1,7 +1,9 @@
# Danish translation for folks.
-# Copyright (C) 2012 The Free Software Foundation
+# Copyright (C) 2012, 2014 The Free Software Foundation
# This file is distributed under the same license as the folks package.
+#
# Kenneth Nielsen <k.nielsen81@gmail.com>, 2012.
+# Ask Hjorth Larsen <asklarsen@gmail.com>, 2014.
#
# persona -> persona
# store i "persona store" -> kilde
@@ -13,9 +15,9 @@ msgid ""
msgstr ""
"Project-Id-Version: folks master\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2013-03-17 08:26+0100\n"
-"PO-Revision-Date: 2013-03-16 16:30+0100\n"
-"Last-Translator: Kenneth Nielsen <k.nielsen81@gmail.com>\n"
+"POT-Creation-Date: 2014-03-20 21:06+0100\n"
+"PO-Revision-Date: 2014-03-16 01:09+0100\n"
+"Last-Translator: Ask Hjorth Larsen <asklarsen@gmail.com>\n"
"Language-Team: Danish <dansk@dansk-gruppen.dk>\n"
"Language: da\n"
"MIME-Version: 1.0\n"
@@ -23,6 +25,85 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+#: ../backends/bluez/bluez-backend.vala:600
+msgid ""
+"No BlueZ 5 object manager running, so the BlueZ backend will be inactive. "
+"Either your BlueZ installation is too old (only version 5 is supported) or "
+"the service can’t be started."
+msgstr ""
+"Der kører ikke nogen BlueZ 5-objekthåndtering, så BlueZ-motoren vil være "
+"inaktiv. Enten er din BlueZ-installation for gammel (kun version 5 "
+"understøttes), eller tjenesten kan ikke startes."
+
+#: ../backends/bluez/bluez-backend.vala:613
+msgid ""
+"Error connecting to OBEX transfer daemon over D-Bus. Ensure BlueZ and obexd "
+"are installed."
+msgstr ""
+"Fejl ved forbindelse til OBEX-overførselsdæmon over D-Bus. Sikr dig at BlueZ "
+"og obexd er installeret."
+
+#. Translators: the parameter is an error message.
+#: ../backends/bluez/bluez-persona-store.vala:385
+#, c-format
+msgid "Error reading the transferred address book file: %s"
+msgstr "Fejl ved læsning af den overførte adressebogsfil: %s"
+
+#. Translators: the first parameter is the name of the
+#. * failed transfer, and the second is a Bluetooth device
+#. * alias.
+#: ../backends/bluez/bluez-persona-store.vala:667
+#, fuzzy, c-format
+msgid "Error during transfer of the address book ‘%s’ from "
+msgstr ""
+"Fejl under overførsel af adressebogen \"%s\" fra Bluetooth-enheden \"%s\"."
+
+#. Translators: the first parameter is the name of the failed
+#. * transfer, and the second is a Bluetooth device alias.
+#: ../backends/bluez/bluez-persona-store.vala:689
+#, c-format
+msgid ""
+"Error during transfer of the address book ‘%s’ from Bluetooth device ‘%s’."
+msgstr ""
+"Fejl under overførsel af adressebogen \"%s\" fra Bluetooth-enheden \"%s\"."
+
+#: ../backends/bluez/bluez-persona-store.vala:782
+#, c-format
+msgid ""
+"Permission to access the address book on Bluetooth device ‘%s’ was denied by "
+"the user."
+msgstr ""
+"Adgangstilladelse til adressebogen på Bluetooth-enheden \"%s\" blev nægtet "
+"af brugeren."
+
+#. Translators: the first parameter is a Bluetooth device
+#. * alias, and the second is an error message.
+#: ../backends/bluez/bluez-persona-store.vala:789
+#, c-format
+msgid "An OBEX address book transfer from device ‘%s’ could not be started: %s"
+msgstr ""
+"En OBEX-overførsel af adressebog fra enheden \"%s\" kunne ikke startes: %s"
+
+#. Translators: the first parameter is a Bluetooth device
+#. * alias, and the second is an error message.
+#: ../backends/bluez/bluez-persona-store.vala:829
+#, c-format
+msgid "The OBEX address book transfer from device ‘%s’ failed: %s"
+msgstr "OBEX-overførslen af adressebog fra enheden \"%s\" mislykkedes: %s"
+
+#. Translators: the first parameter is a Bluetooth device
+#. * alias, and the second is an error message.
+#: ../backends/bluez/bluez-persona-store.vala:846
+#, c-format
+msgid ""
+"Error during transfer of the address book from Bluetooth device ‘%s’: %s"
+msgstr "Fejl under overførsel af adressebogen fra Bluetooth-enheden \"%s\": %s"
+
+#: ../backends/bluez/bluez-persona-store.vala:1064
+#, c-format
+msgid "Bluetooth device ‘%s’ disappeared during address book transfer."
+msgstr "Bluetooth-enheden \"%s\" forsvandt under overførsel af adressebog."
+
# Jeg har lavet en fejlrapport for at få dem til at acceptere at alle strenge bør kunne have en oversættelse
#. The timeout after which we consider a property change to have failed if we
#. * haven't received a property change notification for it.
@@ -38,7 +119,7 @@ msgstr "Starred in Android"
#. Translators: the first parameter is an address book
#. * URI and the second is a persona UID.
-#: ../backends/eds/lib/edsf-persona-store.vala:671
+#: ../backends/eds/lib/edsf-persona-store.vala:674
#, c-format
msgid "Address book ‘%s’ is offline, so contact ‘%s’ cannot be removed."
msgstr ""
@@ -46,61 +127,61 @@ msgstr ""
#. Translators: the first parameter is an address book
#. * URI and the second is an error message.
-#: ../backends/eds/lib/edsf-persona-store.vala:677
+#: ../backends/eds/lib/edsf-persona-store.vala:680
#, c-format
msgid "Permission denied to remove contact ‘%s’: %s"
msgstr "Nægtet tilladelse til at fjerne kontakt \"%s\": %s"
#. Translators: the parameter is an error message.
-#: ../backends/eds/lib/edsf-persona-store.vala:682
+#: ../backends/eds/lib/edsf-persona-store.vala:685
#, c-format
msgid "Removing contacts isn't supported by this persona store: %s"
msgstr "At fjerne kontakter er ikke understøttet af denne personakilde: %s"
-#: ../backends/eds/lib/edsf-persona-store.vala:711
+#: ../backends/eds/lib/edsf-persona-store.vala:714
#, c-format
msgid "Can't remove contact ‘%s’: %s"
msgstr "Kan ikke fjerne \"%s\": %s"
#. Translators: the parameter is an address book
#. * URI.
-#: ../backends/eds/lib/edsf-persona-store.vala:801
-#: ../backends/eds/lib/edsf-persona-store.vala:992
+#: ../backends/eds/lib/edsf-persona-store.vala:803
+#: ../backends/eds/lib/edsf-persona-store.vala:994
#, c-format
msgid "Address book ‘%s’ is offline."
msgstr "Adressebogen \"%s\" er offline."
#. Translators: the first parameter is an address
#. * book URI and the second is an error message.
-#: ../backends/eds/lib/edsf-persona-store.vala:806
-#: ../backends/eds/lib/edsf-persona-store.vala:997
+#: ../backends/eds/lib/edsf-persona-store.vala:808
+#: ../backends/eds/lib/edsf-persona-store.vala:999
#, c-format
msgid "Permission denied to open address book ‘%s’: %s"
msgstr "Nægtet tilladelse til at åbne adressebogen \"%s\": %s"
#. Translators: the first parameter is an address book URI
#. * and the second is an error message.
-#: ../backends/eds/lib/edsf-persona-store.vala:839
+#: ../backends/eds/lib/edsf-persona-store.vala:841
#, c-format
msgid "Couldn't open address book ‘%s’: %s"
msgstr "Kunne ikke åbne adressebogen \"%s\": %s"
#. Translators: the parameteter is an error message.
-#: ../backends/eds/lib/edsf-persona-store.vala:905
-#: ../backends/eds/lib/edsf-persona-store.vala:935
+#: ../backends/eds/lib/edsf-persona-store.vala:907
+#: ../backends/eds/lib/edsf-persona-store.vala:937
#, c-format
msgid "Couldn't get address book capabilities: %s"
msgstr "Kunne ikke hente adressebogsevner: %s"
#. Translators: the parameter is an address book URI.
-#: ../backends/eds/lib/edsf-persona-store.vala:951
+#: ../backends/eds/lib/edsf-persona-store.vala:953
#, c-format
msgid "Couldn't get view for address book ‘%s’."
msgstr "Kunne ikke hente visning for adressebogen \"%s\"."
#. Translators: the first parameter is an address book URI
#. * and the second is an error message.
-#: ../backends/eds/lib/edsf-persona-store.vala:1030
+#: ../backends/eds/lib/edsf-persona-store.vala:1032
#, c-format
msgid "Couldn't get view for address book ‘%s’: %s"
msgstr "Kunne ikke hente visning for adressebogen \"%s\": %s"
@@ -108,119 +189,119 @@ msgstr "Kunne ikke hente visning for adressebogen \"%s\": %s"
#. Translators: the parameter is the name of a property on a
#. * contact, formatted in the normal GObject style (e.g.
#. * lowercase with hyphens to separate words).
-#: ../backends/eds/lib/edsf-persona-store.vala:1390
+#: ../backends/eds/lib/edsf-persona-store.vala:1304
#, c-format
msgid "Changing the ‘%s’ property failed due to reaching the timeout."
msgstr "Ændring af \"%s\"-egenskaben mislykkedes på grund af tidsudløb."
-#: ../backends/eds/lib/edsf-persona-store.vala:1428
+#: ../backends/eds/lib/edsf-persona-store.vala:1338
#: ../folks/avatar-details.vala:63
msgid "Avatar is not writeable on this contact."
msgstr "Profilbillede kan ikke skrives til denne kontakt."
-#: ../backends/eds/lib/edsf-persona-store.vala:1449
+#: ../backends/eds/lib/edsf-persona-store.vala:1359
#: ../folks/web-service-details.vala:123
msgid "Web service addresses are not writeable on this contact."
msgstr "Webtjenesteadresse kan ikke skrives til denne kontakt."
-#: ../backends/eds/lib/edsf-persona-store.vala:1485
+#: ../backends/eds/lib/edsf-persona-store.vala:1395
#: ../folks/url-details.vala:152
msgid "URLs are not writeable on this contact."
msgstr "URL'er kan ikke skrives til denne kontakt."
-#: ../backends/eds/lib/edsf-persona-store.vala:1566
+#: ../backends/eds/lib/edsf-persona-store.vala:1476
#: ../folks/local-id-details.vala:64
msgid "Local IDs are not writeable on this contact."
msgstr "Lokale id'er kan ikke skrives til denne kontakt."
-#: ../backends/eds/lib/edsf-persona-store.vala:1595
+#: ../backends/eds/lib/edsf-persona-store.vala:1505
msgid "The contact cannot be marked as favourite."
msgstr "Kontakten kan ikke markeres som favorit."
#. Translators: the parameter is an error message.
-#: ../backends/eds/lib/edsf-persona-store.vala:1667
+#: ../backends/eds/lib/edsf-persona-store.vala:1577
#, c-format
msgid "Can't update avatar: %s"
msgstr "Kan ikke opdatere profilbillede: %s"
-#: ../backends/eds/lib/edsf-persona-store.vala:1678
+#: ../backends/eds/lib/edsf-persona-store.vala:1588
#: ../folks/email-details.vala:120
msgid "E-mail addresses are not writeable on this contact."
msgstr "E-mail-adresse kan ikke skrives til denne kontakt."
-#: ../backends/eds/lib/edsf-persona-store.vala:1696
-#: ../folks/phone-details.vala:224
+#: ../backends/eds/lib/edsf-persona-store.vala:1606
+#: ../folks/phone-details.vala:255
msgid "Phone numbers are not writeable on this contact."
msgstr "Telefonnumre kan ikke skrives til denne kontakt."
-#: ../backends/eds/lib/edsf-persona-store.vala:1714
+#: ../backends/eds/lib/edsf-persona-store.vala:1624
#: ../folks/postal-address-details.vala:361
msgid "Postal addresses are not writeable on this contact."
msgstr "Postadresser kan ikke skrives til denne kontakt."
-#: ../backends/eds/lib/edsf-persona-store.vala:1785
-#: ../folks/name-details.vala:283
+#: ../backends/eds/lib/edsf-persona-store.vala:1695
+#: ../folks/name-details.vala:454
msgid "Full name is not writeable on this contact."
msgstr "Fulde navn kan ikke skrives til denne kontakt."
-#: ../backends/eds/lib/edsf-persona-store.vala:1807
-#: ../folks/name-details.vala:321
+#: ../backends/eds/lib/edsf-persona-store.vala:1717
+#: ../folks/name-details.vala:492
msgid "Nickname is not writeable on this contact."
msgstr "Kaldenavn kan ikke skrives til denne kontakt."
-#: ../backends/eds/lib/edsf-persona-store.vala:1829
+#: ../backends/eds/lib/edsf-persona-store.vala:1739
#: ../folks/note-details.vala:138
msgid "Notes are not writeable on this contact."
msgstr "Noter kan ikke skrives til denne kontakt."
-#: ../backends/eds/lib/edsf-persona-store.vala:1861
+#: ../backends/eds/lib/edsf-persona-store.vala:1771
#: ../folks/birthday-details.vala:62
msgid "Birthday is not writeable on this contact."
msgstr "Fødselsdag kan ikke skrives til denne kontakt."
-#: ../backends/eds/lib/edsf-persona-store.vala:1905
+#: ../backends/eds/lib/edsf-persona-store.vala:1815
#: ../folks/role-details.vala:279
msgid "Roles are not writeable on this contact."
msgstr "Roller kan ikke skrives til denne kontakt."
-#: ../backends/eds/lib/edsf-persona-store.vala:2006
-#: ../folks/name-details.vala:246
+#: ../backends/eds/lib/edsf-persona-store.vala:1916
+#: ../folks/name-details.vala:417
msgid "Structured name is not writeable on this contact."
msgstr "Struktureret navn kan ikke skrives til denne kontakt."
-#: ../backends/eds/lib/edsf-persona-store.vala:2045
+#: ../backends/eds/lib/edsf-persona-store.vala:1955
#: ../folks/im-details.vala:136
msgid "IM addresses are not writeable on this contact."
msgstr "IM-adresser kan ikke skrives til denne kontakt."
-#: ../backends/eds/lib/edsf-persona-store.vala:2095
+#: ../backends/eds/lib/edsf-persona-store.vala:2005
#: ../folks/group-details.vala:174
msgid "Groups are not writeable on this contact."
msgstr "Grupper kan ikke skrives til denne kontakt."
-#: ../backends/eds/lib/edsf-persona-store.vala:2110
+#: ../backends/eds/lib/edsf-persona-store.vala:2020
msgid "My Contacts is only available for Google Contacts"
msgstr "Mine kontakter er kun tilgængelige for Google-kontakter"
-#: ../backends/eds/lib/edsf-persona-store.vala:2181
+#: ../backends/eds/lib/edsf-persona-store.vala:2091
#: ../folks/gender-details.vala:79
msgid "Gender is not writeable on this contact."
msgstr "Køn kan ikke skrives til denne kontakt."
-#: ../backends/eds/lib/edsf-persona-store.vala:2219
-#: ../folks/anti-linkable.vala:81
+#: ../backends/eds/lib/edsf-persona-store.vala:2129
+#: ../folks/anti-linkable.vala:84
msgid "Anti-links are not writeable on this contact."
msgstr "Anti-henvisninger kan ikke skrives til denne kontakt."
-#: ../backends/eds/lib/edsf-persona-store.vala:2262
-#: ../folks/location-details.vala:129
+#: ../backends/eds/lib/edsf-persona-store.vala:2172
+#: ../folks/location-details.vala:135
msgid "Location is not writeable on this contact."
msgstr "Placering er skrivebeskyttet for denne kontakt."
#. Translators: the first parameter is a non-human-readable
#. * property name and the second parameter is an error
#. * message.
-#: ../backends/eds/lib/edsf-persona-store.vala:2439
+#: ../backends/eds/lib/edsf-persona-store.vala:2485
#, c-format
msgid "Property ‘%s’ is not writeable: %s"
msgstr "Egenskaben \"%s\" er ikke skrivbar: %s"
@@ -228,42 +309,42 @@ msgstr "Egenskaben \"%s\" er ikke skrivbar: %s"
#. Translators: the first parameter is a non-human-readable
#. * property name and the second parameter is an error
#. * message.
-#: ../backends/eds/lib/edsf-persona-store.vala:2448
+#: ../backends/eds/lib/edsf-persona-store.vala:2494
#, c-format
msgid "Invalid value for property ‘%s’: %s"
msgstr "Ugyldig værdi for egenskaben \"%s\": %s"
#. Translators: the first parameter is a non-human-readable
#. * property name and the second parameter is an error message.
-#: ../backends/eds/lib/edsf-persona-store.vala:2474
+#: ../backends/eds/lib/edsf-persona-store.vala:2520
#, c-format
msgid "Unknown error setting property ‘%s’: %s"
msgstr "Ukendt fejl ved indstilling af egenskaben \"%s\": %s"
#. Translators: the first parameter is a filename, and
#. * the second is an error message.
-#: ../backends/key-file/kf-persona-store.vala:233
+#: ../backends/key-file/kf-persona-store.vala:234
#, c-format
msgid "The relationship key file '%s' could not be loaded: %s"
msgstr "Forholdsnøglefilen \"%s\" kunne ikke indlæses: %s"
#. Translators: the first parameter is a path, and the
#. * second is an error message.
-#: ../backends/key-file/kf-persona-store.vala:255
+#: ../backends/key-file/kf-persona-store.vala:256
#, c-format
msgid "The relationship key file directory '%s' could not be created: %s"
msgstr "Kataloget \"%s\" til forholdsnøglefilen kunne ikke blive oprettet: %s"
#. Translators: the first parameter is a filename, and
#. * the second is an error message.
-#: ../backends/key-file/kf-persona-store.vala:279
+#: ../backends/key-file/kf-persona-store.vala:280
#, c-format
msgid "The relationship key file '%s' could not be created: %s"
msgstr "Forholdsnøglefilen \"%s\" kunne ikke blive oprettet: %s"
#. Translators: the first parameter is a filename, the second is
#. * an error message.
-#: ../backends/key-file/kf-persona-store.vala:470
+#: ../backends/key-file/kf-persona-store.vala:471
#, c-format
msgid "Could not write updated key file '%s': %s"
msgstr "Kunne ikke skrive opdateret nøglefil \"%s\": %s"
@@ -273,13 +354,13 @@ msgstr "Kunne ikke skrive opdateret nøglefil \"%s\": %s"
#. * an IM address (e.g. “foo@jabber.org”), the second is
#. * the name of a protocol (e.g. “jabber”) and the third is
#. * an error message.
-#: ../backends/key-file/kf-persona.vala:172
+#: ../backends/key-file/kf-persona.vala:174
#, c-format
msgid "Invalid IM address ‘%s’ for protocol ‘%s’: %s"
msgstr "Ugyldig IM-adresse \"%s\" for protokol \"%s\": %s"
#. Translators: the parameter is an error message.
-#: ../backends/key-file/kf-persona.vala:430
+#: ../backends/key-file/kf-persona.vala:432
#, c-format
msgid "Couldn't load data from key file: %s"
msgstr "Kunne ikke indlæse data fra nøglefil: %s"
@@ -304,30 +385,27 @@ msgstr "Ingen kontaktevner fundet."
msgid "Error opening contacts view."
msgstr "Fejl ved åbning af kontaktvisningen."
-#. Translators: the first parameter is the display name for
-#. * the Telepathy account, and the second is an error
-#. * message.
-#: ../backends/telepathy/lib/tpf-persona-store.vala:814
-#, c-format
+#: ../backends/ofono/ofono-backend.vala:196
msgid ""
-"Failed to determine whether we can set aliases on Telepathy account '%s': %s"
+"No oFono object manager running, so the oFono backend will be inactive. "
+"Either oFono isn’t installed or the service can’t be started."
msgstr ""
-"Kunne ikke finde ud af om vi kan indstille aliasser på Telepathy-kontoen \"%s"
-"\": %s"
+"Der kører ikke nogen oFono-objekthåndtering, så oFono-motoren vil være "
+"inaktiv. Enten er oFono ikke installeret, eller tjenesten kan ikke startes."
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1278
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1248
msgid "Telepathy contacts representing the local user may not be removed."
msgstr ""
"Telepathy-kontakter som repræsenterer den lokale bruger må ikke fjernes."
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1289
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1259
#, c-format
msgid "Failed to remove a persona from store: %s"
msgstr "Kunne ikke fjerne en persona fra kilden: %s"
#. Translators: the first two parameters are store identifiers and
#. * the third is a contact identifier.
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1324
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1294
#, c-format
msgid ""
"Persona store (%s, %s) requires the following details:\n"
@@ -336,18 +414,18 @@ msgstr ""
"Personakilde (%s, %s) kræver følgende detaljer:\n"
" kontakt (givet: \"%s\")\n"
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1339
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1309
msgid "Cannot create a new Telepathy contact while offline."
msgstr "Kan ikke oprette en Telepathy-kontakt i offlinetilstand."
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1357
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1327
#, c-format
msgid "Failed to add a persona from details: %s"
msgstr "Kunne ikke tilføje en persona fra detaljerne %s"
#. Translators: "telepathy-logger" is the name of an application,
#. * and should not be translated.
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1377
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1347
msgid ""
"Failed to change favorite without a connection to the telepathy-logger "
"service."
@@ -355,7 +433,7 @@ msgstr ""
"Kunne ikke ændre favorit uden en forbindelse til \"telepathy-logger\"-"
"tjenesten."
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1383
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1353
msgid ""
"Failed to change favorite status of Telepathy Persona because it has no "
"attached TpContact."
@@ -364,45 +442,45 @@ msgstr ""
"TpContact."
#. Translators: the parameter is a contact identifier.
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1401
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1371
#, c-format
msgid "Failed to change favorite status for Telepathy contact ‘%s’."
msgstr "Kunne ikke ændre favoritstatus for Telepathy-kontakt \"%s\"."
#. Translators: the parameter is an error message.
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1433
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1403
#, c-format
msgid "Failed to change contact's alias: %s"
msgstr "Kunne ikke ændre kontakts alias: %s"
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1514
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1484
msgid "Extended information may only be set on the user's Telepathy contact."
msgstr "Udvidet information må kun indstilles på brugerens Telepathy-kontakt."
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1543
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1513
msgid ""
"Extended information cannot be written because the store is disconnected."
msgstr "Udvidet information kan ikke skrives fordi kilden er afkoblet."
-#: ../backends/telepathy/lib/tpf-persona.vala:499
-#: ../backends/telepathy/lib/tpf-persona.vala:520
-#: ../backends/telepathy/lib/tpf-persona.vala:572
-#: ../backends/telepathy/lib/tpf-persona.vala:586
+#: ../backends/telepathy/lib/tpf-persona.vala:511
+#: ../backends/telepathy/lib/tpf-persona.vala:532
+#: ../backends/telepathy/lib/tpf-persona.vala:584
+#: ../backends/telepathy/lib/tpf-persona.vala:598
#, c-format
msgid "Failed to change group membership: %s"
msgstr "Kunne ikke ændre gruppemedlemsskab: %s"
#. Translators: "account" refers to an instant messaging
#. * account.
-#: ../backends/telepathy/lib/tpf-persona.vala:502
-#: ../backends/telepathy/lib/tpf-persona.vala:575
+#: ../backends/telepathy/lib/tpf-persona.vala:514
+#: ../backends/telepathy/lib/tpf-persona.vala:587
msgid "Account is offline."
msgstr "Konto er offline."
#. Translators: the first parameter is the unknown key that
#. * was received with the details params, and the second
#. * identifies the persona store.
-#: ../backends/tracker/lib/trf-persona-store.vala:742
+#: ../backends/tracker/lib/trf-persona-store.vala:743
#, c-format
msgid "Unrecognized parameter '%s' passed to persona store '%s'."
msgstr "Ukendt parameter \"%s\" givet til personakilde \"%s\"."
@@ -413,19 +491,19 @@ msgstr "Alias kan ikke skrives til denne kontakt."
#. Translators: the first parameter is a folder path and the second
#. * is an error message.
-#: ../folks/backend-store.vala:627
+#: ../folks/backend-store.vala:651
#, c-format
msgid "Error listing contents of folder '%s': %s"
msgstr "Fejl ved visning af indhold i mappen \"%s\": %s"
#. Translators: the parameter is a filename.
-#: ../folks/backend-store.vala:757
+#: ../folks/backend-store.vala:786
#, c-format
msgid "File or directory '%s' does not exist."
msgstr "Fil eller mappe \"%s\" eksisterer ikke."
#. Translators: the parameter is a filename.
-#: ../folks/backend-store.vala:763
+#: ../folks/backend-store.vala:792
#, c-format
msgid "Failed to get content type for '%s'."
msgstr "Kunne ikke hente indholdstype for \"%s\"."
@@ -447,31 +525,31 @@ msgstr "IM-adressen \"%s\" kunne ikke forstås."
#. Translators: the first parameter is a persona store identifier
#. * and the second is an error message.
-#: ../folks/individual-aggregator.vala:935
+#: ../folks/individual-aggregator.vala:1040
#, c-format
msgid "Error preparing persona store '%s': %s"
msgstr "Fejl ved forberedelse af personakilde \"%s\": %s"
#. Translators: the parameter is a property name.
-#: ../folks/individual-aggregator.vala:1158
-#: ../folks/individual-aggregator.vala:1386
+#: ../folks/individual-aggregator.vala:1269
+#: ../folks/individual-aggregator.vala:1536
#, c-format
msgid "Unknown property '%s' in linkable property list."
msgstr "Ukendt egenskab \"%s\" i sammenkædelig egenskabsliste."
#. Translators: the first parameter is a store identifier
#. * and the second parameter is an error message.
-#: ../folks/individual-aggregator.vala:1857
+#: ../folks/individual-aggregator.vala:2022
#, c-format
msgid "Failed to add contact for persona store ID '%s': %s"
msgstr "Kunne ikke tilføje kontakt til personakilde-id \"%s\": %s"
-#: ../folks/individual-aggregator.vala:1958
+#: ../folks/individual-aggregator.vala:2119
msgid "Can’t link personas with no primary store."
msgstr "Kan ikke sammenkæde personaer uden en primær kilde."
-#: ../folks/individual-aggregator.vala:1959
-#: ../folks/individual-aggregator.vala:2291
+#: ../folks/individual-aggregator.vala:2120
+#: ../folks/individual-aggregator.vala:2451
#, c-format
msgid ""
"Persona store ‘%s:%s’ is configured as primary, but could not be found or "
@@ -480,8 +558,8 @@ msgstr ""
"Personakilde \"%s:%s\" er konfigureret som den primære, men kunne ikke "
"findes eller indlæses."
-#: ../folks/individual-aggregator.vala:1960
-#: ../folks/individual-aggregator.vala:2292
+#: ../folks/individual-aggregator.vala:2121
+#: ../folks/individual-aggregator.vala:2452
#, c-format
msgid ""
"Check the relevant service is running, or change the default store in that "
@@ -490,29 +568,81 @@ msgstr ""
"Tjek om den relevante tjeneste kører, eller ændr standardkilden i den "
"tjeneste eller ved hjælp at GSettings-nøglen “%s”."
-#: ../folks/individual-aggregator.vala:1992
+#: ../folks/individual-aggregator.vala:2153
msgid "Anti-links can't be removed between personas being linked."
msgstr ""
"Anti-henvisninger kan ikke fjernes mellem personaer som er ved at blive "
"sammenkædet."
-#: ../folks/individual-aggregator.vala:2290
+#: ../folks/individual-aggregator.vala:2450
msgid "Can’t add personas with no primary store."
msgstr "Kan ikke tilføje personaer uden en primær kilde."
-#: ../folks/individual-aggregator.vala:2301
+#: ../folks/individual-aggregator.vala:2461
#, c-format
msgid "Can't write to requested property (“%s”) of the writeable store."
msgstr ""
"Kan ikke skrive til den anmodede egenskab (“%s”) i den skrivbare kilde."
-#: ../folks/individual.vala:217 ../folks/individual.vala:370
-#: ../folks/individual.vala:479 ../folks/individual.vala:730
-#: ../folks/individual.vala:808
+#: ../folks/individual.vala:216 ../folks/individual.vala:402
+#: ../folks/individual.vala:511 ../folks/individual.vala:762
+#: ../folks/individual.vala:840
#, c-format
msgid "Failed to change property ‘%s’: No suitable personas were found."
msgstr "Kunne ikke ændre egenskaben \"%s\": Ingen passende personaer fundet."
+#. Translators: This is the default name for an Individual
+#. * when displayed in the UI if no personal details are available
+#. * for them.
+#: ../folks/individual.vala:1951
+msgid "Unnamed Person"
+msgstr "Unavngivet person"
+
+# Okay, alt dette betyder bare fornavn-mellemnavn-efternavn, adskilt af punktummer (%t)
+#
+#. FIXME: Ideally we’d use a format string translated to the locale of the
+#. * persona whose name is being formatted, but no backend provides
+#. * information about personas’ locales, so we have to settle for the
+#. * current user’s locale.
+#. *
+#. * We thought about using nl_langinfo(_NL_NAME_NAME_FMT) here, but
+#. * decided against it because:
+#. * 1. It’s not the best documented API in the world, and its stability
+#. * is in question.
+#. * 2. An attempt to improve the interface in glibc met with a wall of
+#. * complaints: https://sourceware.org/bugzilla/show_bug.cgi?id=14641.
+#. *
+#. * However, we do re-use the string format placeholders from
+#. * _NL_NAME_NAME_FMT (as documented here:
+#. * http://lh.2xlibre.net/values/name_fmt/) because there’s a chance glibc
+#. * might eventually grow a useful interface for this.
+#. *
+#. * It does mean we have to implement our own parser for the name_fmt
+#. * format though, since glibc doesn’t provide a formatting function.
+#. Translators: This is a format string used to convert structured names
+#. * to a single string. It should be translated to the predominant
+#. * semi-formal name format for your locale, using the placeholders
+#. * documented here: http://lh.2xlibre.net/values/name_fmt/. You may be
+#. * able to re-use the existing glibc format string for your locale on that
+#. * page if it’s suitable.
+#. *
+#. * More explicitly: the supported placeholders are %f, %F, %g, %G, %m, %M,
+#. * %t. The romanisation modifier (e.g. %Rf) is recognized but ignored.
+#. * %s, %S and %d are all replaced by the same thing (the ‘Honorific
+#. * Prefixes’ from vCard) so please avoid using more than one.
+#. *
+#. * For example, the format string ‘%g%t%m%t%f’ expands to ‘John Andrew
+#. * Lees’ when used for a persona with first name ‘John’, additional names
+#. * ‘Andrew’ and family names ‘Lees’.
+#. *
+#. * If you need additional placeholders with other information or
+#. * punctuation, please file a bug against libfolks:
+#. * https://bugzilla.gnome.org/enter_bug.cgi?product=folks
+#.
+#: ../folks/name-details.vala:268
+msgid "%g%t%m%t%f"
+msgstr "%g%t%m%t%f"
+
#: ../folks/org.freedesktop.folks.gschema.xml.in.h:1
msgid "Primary store ID"
msgstr "Id for primær kilde"
@@ -533,35 +663,35 @@ msgstr ""
msgid "%s, %s, %s, %s, %s, %s, %s"
msgstr "%s, %s, %s, %s, %s, %s, %s"
-#: ../folks/presence-details.vala:159
+#: ../folks/presence-details.vala:171
msgid "Unknown status"
msgstr "Ukendt status"
-#: ../folks/presence-details.vala:161
+#: ../folks/presence-details.vala:173
msgid "Offline"
msgstr "Offline"
-#: ../folks/presence-details.vala:165
+#: ../folks/presence-details.vala:177
msgid "Error"
msgstr "Fejl"
-#: ../folks/presence-details.vala:167
+#: ../folks/presence-details.vala:179
msgid "Available"
msgstr "Tilgængelig"
-#: ../folks/presence-details.vala:169
+#: ../folks/presence-details.vala:181
msgid "Away"
msgstr "Ikke til stede"
-#: ../folks/presence-details.vala:171
+#: ../folks/presence-details.vala:183
msgid "Extended away"
msgstr "Længerevarende fravær"
-#: ../folks/presence-details.vala:173
+#: ../folks/presence-details.vala:185
msgid "Busy"
msgstr "Optaget"
-#: ../folks/presence-details.vala:175
+#: ../folks/presence-details.vala:187
msgid "Hidden"
msgstr "Skjult"
@@ -662,54 +792,54 @@ msgstr "Kildeprogramnavn (backend) (standard: \"pidgin\")"
msgid "Source filename (default: specific to source backend)"
msgstr "Kildefilnavn (standard: specifik for kildeprogrammet (backend))"
-#: ../tools/import.vala:57
+#: ../tools/import.vala:58
msgid "— import meta-contact information to libfolks"
msgstr "— importér metakontaktinformation til libfolks"
#. Translators: the parameter is an error message.
-#: ../tools/import.vala:67
+#: ../tools/import.vala:68
#, c-format
msgid "Couldn't parse command line options: %s"
msgstr "Kunne ikke fortolke kommandolinjetilvalg: %s"
#. Translators: the parameter is an error message.
-#: ../tools/import.vala:108
+#: ../tools/import.vala:109
#, c-format
msgid "Couldn't load the backends: %s"
msgstr "Kunne ikke indlæse kildeprogrammerne: %s"
#. Translators: the parameter is a backend identifier.
-#: ../tools/import.vala:119
+#: ../tools/import.vala:120
#, c-format
msgid "Couldn't load the ‘%s’ backend."
msgstr "Kunne ikke indlæse kildeprogrammet \"%s\"."
#. Translators: the first parameter is a backend identifier and the
#. * second parameter is an error message.
-#: ../tools/import.vala:132
+#: ../tools/import.vala:133
#, c-format
msgid "Couldn't prepare the ‘%s’ backend: %s"
msgstr "Kunne ikke forberede kildeprogrammet \"%s\": %s"
#. Translators: the parameter is a backend identifier.
-#: ../tools/import.vala:145
+#: ../tools/import.vala:146
#, c-format
msgid "Couldn't load the ‘%s’ backend's persona store."
msgstr "Kunne ikke indlæse personakilder for kildeprogrammet \"%s\"."
-#: ../tools/import.vala:166
+#: ../tools/import.vala:167
#, c-format
msgid "Couldn't prepare the ‘%s’ backend's persona store: %s"
msgstr "Kunne ikke forberede personakilden for kildeprogrammet \"%s\": %s"
#. Translators: the parameter is an error message.
-#: ../tools/import.vala:184
+#: ../tools/import.vala:185
#, c-format
msgid "Error importing contacts: %s"
msgstr "Fejl ved import af kontakter: %s"
#. Translators: both parameters are identifiers for backends.
-#: ../tools/import.vala:198
+#: ../tools/import.vala:199
#, c-format
msgid ""
"Unrecognized source backend name ‘%s’. ‘%s’ is currently the only supported "
@@ -717,3 +847,10 @@ msgid ""
msgstr ""
"Ukendt navn \"%s\" for kildeprogram. \"%s\" er på nuværende tidspunkt det "
"eneste understøttede kildeprogram."
+
+#~ msgid ""
+#~ "Failed to determine whether we can set aliases on Telepathy account '%s': "
+#~ "%s"
+#~ msgstr ""
+#~ "Kunne ikke finde ud af om vi kan indstille aliasser på Telepathy-kontoen "
+#~ "\"%s\": %s"
diff --git a/po/fr.po b/po/fr.po
index 29fe1c45..71c235c5 100644
--- a/po/fr.po
+++ b/po/fr.po
@@ -8,10 +8,11 @@
msgid ""
msgstr ""
"Project-Id-Version: folks master\n"
-"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?"
-"product=folks&keywords=I18N+L10N&component=general\n"
-"POT-Creation-Date: 2013-02-20 14:29+0000\n"
-"PO-Revision-Date: 2013-02-20 20:19+0100\n"
+"Report-Msgid-Bugs-To: "
+"http://bugzilla.gnome.org/enter_bug.cgi?product=folks&keywords=I18N+L10N&component=general"
+"\n"
+"POT-Creation-Date: 2014-03-15 05:53+0000\n"
+"PO-Revision-Date: 2014-03-15 20:32+0100\n"
"Last-Translator: Bruno Brouard <annoa.b@gmail.com>\n"
"Language-Team: GNOME French Team <gnomefr@traduc.org>\n"
"Language: \n"
@@ -20,6 +21,91 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
+#: ../backends/bluez/bluez-backend.vala:600
+msgid ""
+"No BlueZ 5 object manager running, so the BlueZ backend will be inactive. "
+"Either your BlueZ installation is too old (only version 5 is supported) or "
+"the service can’t be started."
+msgstr ""
+"Le gestionnaire d'objets BlueZ 5 n'est pas en cours d'exécution, le moteur "
+"BlueZ sera inactif. Soit votre installation de BlueZ est trop ancienne "
+"(seule la version 5 est prise en charge) soit le service ne peut être "
+"démarré."
+
+#: ../backends/bluez/bluez-backend.vala:613
+msgid ""
+"Error connecting to OBEX transfer daemon over D-Bus. Ensure BlueZ and obexd "
+"are installed."
+msgstr ""
+"Erreur à la connexion au service de transfert OBEX sur D-Bus. Vérifiez que "
+"BlueZ et obexd sont installés."
+
+#. Translators: the parameter is an error message.
+#: ../backends/bluez/bluez-persona-store.vala:385
+#, c-format
+msgid "Error reading the transferred address book file: %s"
+msgstr "Erreur à la lecture du fichier de carnet d'adresses transféré : %s"
+
+#. Translators: the first parameter is the name of the
+#. * failed transfer, and the second is a Bluetooth device
+#. * alias.
+#. Translators: the first parameter is the name of the failed
+#. * transfer, and the second is a Bluetooth device alias.
+#: ../backends/bluez/bluez-persona-store.vala:667
+#: ../backends/bluez/bluez-persona-store.vala:689
+#, c-format
+msgid ""
+"Error during transfer of the address book ‘%s’ from Bluetooth device "
+"‘%s’."
+msgstr ""
+"Erreur lors du transfert du carnet d'adresses « %s » du périphérique "
+"Bluetooth « %s »."
+
+#: ../backends/bluez/bluez-persona-store.vala:782
+#, c-format
+msgid ""
+"Permission to access the address book on Bluetooth device ‘%s’ was "
+"denied by the user."
+msgstr ""
+"L'accès au carnet d'adresses du périphérique Bluetooth « %s » a été "
+"refusé par l'utilisateur."
+
+#. Translators: the first parameter is a Bluetooth device
+#. * alias, and the second is an error message.
+#: ../backends/bluez/bluez-persona-store.vala:789
+#, c-format
+msgid ""
+"An OBEX address book transfer from device ‘%s’ could not be started: %s"
+msgstr ""
+"Un transfert par OBEX d'un carnet d'adresses du périphérique « %s » n'a "
+"pas pu être démarré : %s"
+
+#. Translators: the first parameter is a Bluetooth device
+#. * alias, and the second is an error message.
+#: ../backends/bluez/bluez-persona-store.vala:829
+#, c-format
+msgid "The OBEX address book transfer from device ‘%s’ failed: %s"
+msgstr ""
+"Le transfert par OBEX d'un carnet d'adresses du périphérique « %s » a "
+"échoué : %s"
+
+#. Translators: the first parameter is a Bluetooth device
+#. * alias, and the second is an error message.
+#: ../backends/bluez/bluez-persona-store.vala:846
+#, c-format
+msgid ""
+"Error during transfer of the address book from Bluetooth device ‘%s’: %s"
+msgstr ""
+"Erreur lors du transfert du carnet d'adresses du périphérique Bluetooth "
+"« %s » : %s"
+
+#: ../backends/bluez/bluez-persona-store.vala:1064
+#, c-format
+msgid "Bluetooth device ‘%s’ disappeared during address book transfer."
+msgstr ""
+"Le périphérique Bluetooth « %s » a disparu pendant le transfert du "
+"carnet d'adresses."
+
#. The timeout after which we consider a property change to have failed if we
#. * haven't received a property change notification for it.
#. seconds
@@ -34,72 +120,73 @@ msgstr "Starred in Android"
#. Translators: the first parameter is an address book
#. * URI and the second is a persona UID.
-#: ../backends/eds/lib/edsf-persona-store.vala:671
+#: ../backends/eds/lib/edsf-persona-store.vala:673
#, c-format
-msgid "Address book ‘%s’ is offline, so contact ‘%s’ cannot be removed."
+msgid ""
+"Address book ‘%s’ is offline, so contact ‘%s’ cannot be removed."
msgstr ""
-"Le carnet d'adresses «%s » est hors ligne, par conséquent le contact « %s » "
-"ne peut pas être supprimé."
+"Le carnet d'adresses «%s » est hors ligne, par conséquent le contact "
+"« %s » ne peut pas être supprimé."
#. Translators: the first parameter is an address book
#. * URI and the second is an error message.
-#: ../backends/eds/lib/edsf-persona-store.vala:677
+#: ../backends/eds/lib/edsf-persona-store.vala:679
#, c-format
msgid "Permission denied to remove contact ‘%s’: %s"
msgstr "Permission refusée de supprimer le contact « %s » : %s"
#. Translators: the parameter is an error message.
-#: ../backends/eds/lib/edsf-persona-store.vala:682
+#: ../backends/eds/lib/edsf-persona-store.vala:684
#, c-format
msgid "Removing contacts isn't supported by this persona store: %s"
msgstr ""
"La suppression de contacts n'est pas prise en charge par cet palette de "
"personnages : %s"
-#: ../backends/eds/lib/edsf-persona-store.vala:711
+#: ../backends/eds/lib/edsf-persona-store.vala:713
#, c-format
msgid "Can't remove contact ‘%s’: %s"
msgstr "Impossible de supprimer le contact « %s » : %s"
#. Translators: the parameter is an address book
#. * URI.
-#: ../backends/eds/lib/edsf-persona-store.vala:801
-#: ../backends/eds/lib/edsf-persona-store.vala:992
+#: ../backends/eds/lib/edsf-persona-store.vala:802
+#: ../backends/eds/lib/edsf-persona-store.vala:993
#, c-format
msgid "Address book ‘%s’ is offline."
msgstr "Le carnet d'adresses « %s » est hors ligne."
#. Translators: the first parameter is an address
#. * book URI and the second is an error message.
-#: ../backends/eds/lib/edsf-persona-store.vala:806
-#: ../backends/eds/lib/edsf-persona-store.vala:997
+#: ../backends/eds/lib/edsf-persona-store.vala:807
+#: ../backends/eds/lib/edsf-persona-store.vala:998
#, c-format
msgid "Permission denied to open address book ‘%s’: %s"
msgstr "Permission refusée d'ouvrir le carnet d'adresses « %s » : %s"
#. Translators: the first parameter is an address book URI
#. * and the second is an error message.
-#: ../backends/eds/lib/edsf-persona-store.vala:839
+#: ../backends/eds/lib/edsf-persona-store.vala:840
#, c-format
msgid "Couldn't open address book ‘%s’: %s"
msgstr "Impossible d'ouvrir le carnet d'adresses « %s » : %s"
#. Translators: the parameteter is an error message.
-#: ../backends/eds/lib/edsf-persona-store.vala:905
-#: ../backends/eds/lib/edsf-persona-store.vala:935
+#: ../backends/eds/lib/edsf-persona-store.vala:906
+#: ../backends/eds/lib/edsf-persona-store.vala:936
#, c-format
msgid "Couldn't get address book capabilities: %s"
msgstr "Impossible d'obtenir les capacités du carnet d'adresses : %s"
#. Translators: the parameter is an address book URI.
-#: ../backends/eds/lib/edsf-persona-store.vala:951
+#: ../backends/eds/lib/edsf-persona-store.vala:952
#, c-format
msgid "Couldn't get view for address book ‘%s’."
msgstr "Impossible d'obtenir la vue pour le carnet d'adresses « %s »."
#. Translators: the first parameter is an address book URI
#. * and the second is an error message.
-#: ../backends/eds/lib/edsf-persona-store.vala:1030
+#: ../backends/eds/lib/edsf-persona-store.vala:1031
#, c-format
msgid "Couldn't get view for address book ‘%s’: %s"
msgstr "Impossible d'obtenir la vue pour le carnet d'adresses « %s » : %s"
@@ -107,123 +194,123 @@ msgstr "Impossible d'obtenir la vue pour le carnet d'adresses « %s » : %s"
#. Translators: the parameter is the name of a property on a
#. * contact, formatted in the normal GObject style (e.g.
#. * lowercase with hyphens to separate words).
-#: ../backends/eds/lib/edsf-persona-store.vala:1390
+#: ../backends/eds/lib/edsf-persona-store.vala:1303
#, c-format
msgid "Changing the ‘%s’ property failed due to reaching the timeout."
msgstr ""
-"Le changement de la propriété « %s » a échoué en raison d'un délai d'attente "
-"dépassé."
+"Le changement de la propriété « %s » a échoué en raison d'un délai "
+"d'attente dépassé."
-#: ../backends/eds/lib/edsf-persona-store.vala:1428
+#: ../backends/eds/lib/edsf-persona-store.vala:1337
#: ../folks/avatar-details.vala:63
msgid "Avatar is not writeable on this contact."
msgstr "L'avatar n'est pas modifiable pour ce contact."
-#: ../backends/eds/lib/edsf-persona-store.vala:1449
+#: ../backends/eds/lib/edsf-persona-store.vala:1358
#: ../folks/web-service-details.vala:123
msgid "Web service addresses are not writeable on this contact."
msgstr "Les adresses des services Web ne sont pas modifiables pour ce contact."
-#: ../backends/eds/lib/edsf-persona-store.vala:1485
+#: ../backends/eds/lib/edsf-persona-store.vala:1394
#: ../folks/url-details.vala:152
msgid "URLs are not writeable on this contact."
msgstr "Les URL ne sont pas modifiables pour ce contact."
-#: ../backends/eds/lib/edsf-persona-store.vala:1566
+#: ../backends/eds/lib/edsf-persona-store.vala:1475
#: ../folks/local-id-details.vala:64
msgid "Local IDs are not writeable on this contact."
msgstr "Les identifiants locaux ne sont pas modifiables pour ce contact."
-#: ../backends/eds/lib/edsf-persona-store.vala:1595
+#: ../backends/eds/lib/edsf-persona-store.vala:1504
msgid "The contact cannot be marked as favourite."
msgstr "Impossible de marquer le contact comme favori."
#. Translators: the parameter is an error message.
-#: ../backends/eds/lib/edsf-persona-store.vala:1667
+#: ../backends/eds/lib/edsf-persona-store.vala:1576
#, c-format
msgid "Can't update avatar: %s"
msgstr "Impossible de mettre à jour l'avatar : %s"
-#: ../backends/eds/lib/edsf-persona-store.vala:1678
+#: ../backends/eds/lib/edsf-persona-store.vala:1587
#: ../folks/email-details.vala:120
msgid "E-mail addresses are not writeable on this contact."
msgstr "Les adresses électroniques ne sont pas modifiables pour ce contact."
-#: ../backends/eds/lib/edsf-persona-store.vala:1696
-#: ../folks/phone-details.vala:224
+#: ../backends/eds/lib/edsf-persona-store.vala:1605
+#: ../folks/phone-details.vala:255
msgid "Phone numbers are not writeable on this contact."
msgstr "Les numéros de téléphone ne sont pas modifiables pour ce contact."
-#: ../backends/eds/lib/edsf-persona-store.vala:1714
+#: ../backends/eds/lib/edsf-persona-store.vala:1623
#: ../folks/postal-address-details.vala:361
msgid "Postal addresses are not writeable on this contact."
msgstr "Les adresses postales ne sont pas modifiables pour ce contact."
-#: ../backends/eds/lib/edsf-persona-store.vala:1785
-#: ../folks/name-details.vala:283
+#: ../backends/eds/lib/edsf-persona-store.vala:1694
+#: ../folks/name-details.vala:454
msgid "Full name is not writeable on this contact."
msgstr "Le nom complet n'est pas modifiable pour ce contact."
-#: ../backends/eds/lib/edsf-persona-store.vala:1807
-#: ../folks/name-details.vala:321
+#: ../backends/eds/lib/edsf-persona-store.vala:1716
+#: ../folks/name-details.vala:492
msgid "Nickname is not writeable on this contact."
msgstr "Le pseudonyme n'est pas modifiable pour ce contact."
-#: ../backends/eds/lib/edsf-persona-store.vala:1829
+#: ../backends/eds/lib/edsf-persona-store.vala:1738
#: ../folks/note-details.vala:138
msgid "Notes are not writeable on this contact."
msgstr "Les notes ne sont pas modifiables pour ce contact."
-#: ../backends/eds/lib/edsf-persona-store.vala:1861
+#: ../backends/eds/lib/edsf-persona-store.vala:1770
#: ../folks/birthday-details.vala:62
msgid "Birthday is not writeable on this contact."
msgstr "La date de naissance n'est pas modifiable pour ce contact."
-#: ../backends/eds/lib/edsf-persona-store.vala:1905
+#: ../backends/eds/lib/edsf-persona-store.vala:1814
#: ../folks/role-details.vala:279
msgid "Roles are not writeable on this contact."
msgstr "Les rôles ne sont pas modifiables pour ce contact."
-#: ../backends/eds/lib/edsf-persona-store.vala:2006
-#: ../folks/name-details.vala:246
+#: ../backends/eds/lib/edsf-persona-store.vala:1915
+#: ../folks/name-details.vala:417
msgid "Structured name is not writeable on this contact."
msgstr "Le nom structuré n'est pas modifiable pour ce contact."
-#: ../backends/eds/lib/edsf-persona-store.vala:2045
+#: ../backends/eds/lib/edsf-persona-store.vala:1954
#: ../folks/im-details.vala:136
msgid "IM addresses are not writeable on this contact."
msgstr ""
"Les adresses de messagerie instantanée ne sont pas modifiables pour ce "
"contact."
-#: ../backends/eds/lib/edsf-persona-store.vala:2095
+#: ../backends/eds/lib/edsf-persona-store.vala:2004
#: ../folks/group-details.vala:174
msgid "Groups are not writeable on this contact."
msgstr "Les groupes ne sont pas modifiables pour ce contact."
-#: ../backends/eds/lib/edsf-persona-store.vala:2110
+#: ../backends/eds/lib/edsf-persona-store.vala:2019
msgid "My Contacts is only available for Google Contacts"
msgstr "Mes contacts est seulement disponible pour les contacts Google"
-#: ../backends/eds/lib/edsf-persona-store.vala:2181
+#: ../backends/eds/lib/edsf-persona-store.vala:2090
#: ../folks/gender-details.vala:79
msgid "Gender is not writeable on this contact."
msgstr "Le genre n'est pas modifiable pour ce contact."
-#: ../backends/eds/lib/edsf-persona-store.vala:2219
-#: ../folks/anti-linkable.vala:81
+#: ../backends/eds/lib/edsf-persona-store.vala:2128
+#: ../folks/anti-linkable.vala:84
msgid "Anti-links are not writeable on this contact."
msgstr "Les anti-liens ne sont pas modifiables pour ce contact."
-#: ../backends/eds/lib/edsf-persona-store.vala:2262
-#: ../folks/location-details.vala:129
+#: ../backends/eds/lib/edsf-persona-store.vala:2171
+#: ../folks/location-details.vala:135
msgid "Location is not writeable on this contact."
msgstr "La position n'est pas modifiable pour ce contact."
#. Translators: the first parameter is a non-human-readable
#. * property name and the second parameter is an error
#. * message.
-#: ../backends/eds/lib/edsf-persona-store.vala:2439
+#: ../backends/eds/lib/edsf-persona-store.vala:2484
#, c-format
msgid "Property ‘%s’ is not writeable: %s"
msgstr "La propriété « %s » n'est pas modifiable : %s"
@@ -231,43 +318,47 @@ msgstr "La propriété « %s » n'est pas modifiable : %s"
#. Translators: the first parameter is a non-human-readable
#. * property name and the second parameter is an error
#. * message.
-#: ../backends/eds/lib/edsf-persona-store.vala:2448
+#: ../backends/eds/lib/edsf-persona-store.vala:2493
#, c-format
msgid "Invalid value for property ‘%s’: %s"
msgstr "Valeur non valide pour la propriété « %s » : %s"
#. Translators: the first parameter is a non-human-readable
#. * property name and the second parameter is an error message.
-#: ../backends/eds/lib/edsf-persona-store.vala:2474
+#: ../backends/eds/lib/edsf-persona-store.vala:2519
#, c-format
msgid "Unknown error setting property ‘%s’: %s"
-msgstr "Erreur inconnue au changement de valeur de la propriété « %s » : %s"
+msgstr ""
+"Erreur inconnue au changement de valeur de la propriété « %s » : %s"
#. Translators: the first parameter is a filename, and
#. * the second is an error message.
-#: ../backends/key-file/kf-persona-store.vala:233
+#: ../backends/key-file/kf-persona-store.vala:234
#, c-format
msgid "The relationship key file '%s' could not be loaded: %s"
-msgstr "Le fichier de clé de relation « %s » n'a pas pu être chargé : %s"
+msgstr ""
+"Le fichier de clé de relation « %s » n'a pas pu être chargé : %s"
#. Translators: the first parameter is a path, and the
#. * second is an error message.
-#: ../backends/key-file/kf-persona-store.vala:255
+#: ../backends/key-file/kf-persona-store.vala:256
#, c-format
msgid "The relationship key file directory '%s' could not be created: %s"
msgstr ""
-"Le répertoire du fichier de clé de relation « %s » n'a pas pu être créé : %s"
+"Le répertoire du fichier de clé de relation « %s » n'a pas pu être "
+"créé : %s"
#. Translators: the first parameter is a filename, and
#. * the second is an error message.
-#: ../backends/key-file/kf-persona-store.vala:279
+#: ../backends/key-file/kf-persona-store.vala:280
#, c-format
msgid "The relationship key file '%s' could not be created: %s"
-msgstr "Le fichier de clé de relation « %s » n'a pas pu être créé : %s"
+msgstr ""
+"Le fichier de clé de relation « %s » n'a pas pu être créé : %s"
#. Translators: the first parameter is a filename, the second is
#. * an error message.
-#: ../backends/key-file/kf-persona-store.vala:470
+#: ../backends/key-file/kf-persona-store.vala:471
#, c-format
msgid "Could not write updated key file '%s': %s"
msgstr "Impossible de mettre à jour le fichier de clé « %s » : %s"
@@ -277,7 +368,7 @@ msgstr "Impossible de mettre à jour le fichier de clé « %s » : %s"
#. * an IM address (e.g. “foo@jabber.org”), the second is
#. * the name of a protocol (e.g. “jabber”) and the third is
#. * an error message.
-#: ../backends/key-file/kf-persona.vala:172
+#: ../backends/key-file/kf-persona.vala:174
#, c-format
msgid "Invalid IM address ‘%s’ for protocol ‘%s’: %s"
msgstr ""
@@ -285,7 +376,7 @@ msgstr ""
"« %s » : %s"
#. Translators: the parameter is an error message.
-#: ../backends/key-file/kf-persona.vala:430
+#: ../backends/key-file/kf-persona.vala:432
#, c-format
msgid "Couldn't load data from key file: %s"
msgstr "Impossible de charger les données du fichier de clé : %s"
@@ -310,31 +401,29 @@ msgstr "Aucune capacité de contacts n'a été trouvée."
msgid "Error opening contacts view."
msgstr "Erreur lors de l'ouverture de la vue des contacts."
-#. Translators: the first parameter is the display name for
-#. * the Telepathy account, and the second is an error
-#. * message.
-#: ../backends/telepathy/lib/tpf-persona-store.vala:814
-#, c-format
+#: ../backends/ofono/ofono-backend.vala:196
msgid ""
-"Failed to determine whether we can set aliases on Telepathy account '%s': %s"
+"No oFono object manager running, so the oFono backend will be inactive. "
+"Either oFono isn’t installed or the service can’t be started."
msgstr ""
-"Impossible de déterminer s'il est possible de définir des alias sur le "
-"compte Telepathy « %s » : %s"
+"Le gestionnaire d'objets oFono n'est pas en cours d'exécution, le moteur "
+"oFono sera inactif. Soit oFono n'est pas installé soit le service ne peut "
+"être démarré."
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1278
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1248
msgid "Telepathy contacts representing the local user may not be removed."
msgstr ""
"Les contacts Telepathy représentant l'utilisateur local ne peuvent être "
"supprimés."
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1289
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1259
#, c-format
msgid "Failed to remove a persona from store: %s"
msgstr "Échec de la suppression d'un personnage de la palette : %s"
#. Translators: the first two parameters are store identifiers and
#. * the third is a contact identifier.
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1324
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1294
#, c-format
msgid ""
"Persona store (%s, %s) requires the following details:\n"
@@ -343,26 +432,26 @@ msgstr ""
"La palette de personnages (%s, %s) a besoin des détails suivants :\n"
" contact (fourni : « %s »)\n"
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1339
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1309
msgid "Cannot create a new Telepathy contact while offline."
msgstr "Impossible de créer un nouveau contact Telepathy en mode hors ligne."
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1357
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1327
#, c-format
msgid "Failed to add a persona from details: %s"
msgstr "Échec de l'ajout d'un personnage à partir des détails : %s"
#. Translators: "telepathy-logger" is the name of an application,
#. * and should not be translated.
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1377
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1347
msgid ""
"Failed to change favorite without a connection to the telepathy-logger "
"service."
msgstr ""
-"Échec de la modification du favori sans une connexion au service telepathy-"
-"logger."
+"Échec de la modification du favori sans une connexion au service "
+"telepathy-logger."
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1383
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1353
msgid ""
"Failed to change favorite status of Telepathy Persona because it has no "
"attached TpContact."
@@ -371,54 +460,56 @@ msgstr ""
"possède aucun TpContact attaché."
#. Translators: the parameter is a contact identifier.
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1401
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1371
#, c-format
msgid "Failed to change favorite status for Telepathy contact ‘%s’."
msgstr ""
-"Échec de la modification du statut favori pour le contact Telepathy « %s »."
+"Échec de la modification du statut favori pour le contact Telepathy "
+"« %s »."
#. Translators: the parameter is an error message.
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1433
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1403
#, c-format
msgid "Failed to change contact's alias: %s"
msgstr "Échec de la modification de l'alias du contact : %s"
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1513
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1484
msgid "Extended information may only be set on the user's Telepathy contact."
msgstr ""
"Des informations étendues ne peuvent être définies que sur le contact "
"Telepathy de l'utilisateur."
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1542
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1513
msgid ""
"Extended information cannot be written because the store is disconnected."
msgstr ""
-"Les informations étendues ne peuvent être écrites parce que la palette est "
-"déconnectée."
+"Les informations étendues ne peuvent être écrites parce que la palette "
+"est déconnectée."
-#: ../backends/telepathy/lib/tpf-persona.vala:499
-#: ../backends/telepathy/lib/tpf-persona.vala:520
-#: ../backends/telepathy/lib/tpf-persona.vala:572
-#: ../backends/telepathy/lib/tpf-persona.vala:586
+#: ../backends/telepathy/lib/tpf-persona.vala:511
+#: ../backends/telepathy/lib/tpf-persona.vala:532
+#: ../backends/telepathy/lib/tpf-persona.vala:584
+#: ../backends/telepathy/lib/tpf-persona.vala:598
#, c-format
msgid "Failed to change group membership: %s"
msgstr "Échec de la modification de l'appartenance au groupe : %s"
#. Translators: "account" refers to an instant messaging
#. * account.
-#: ../backends/telepathy/lib/tpf-persona.vala:502
-#: ../backends/telepathy/lib/tpf-persona.vala:575
+#: ../backends/telepathy/lib/tpf-persona.vala:514
+#: ../backends/telepathy/lib/tpf-persona.vala:587
msgid "Account is offline."
msgstr "Le compte est hors ligne."
#. Translators: the first parameter is the unknown key that
#. * was received with the details params, and the second
#. * identifies the persona store.
-#: ../backends/tracker/lib/trf-persona-store.vala:742
+#: ../backends/tracker/lib/trf-persona-store.vala:743
#, c-format
msgid "Unrecognized parameter '%s' passed to persona store '%s'."
msgstr ""
-"Paramètre non reconnu « %s » transmis à la palette de personnages « %s »."
+"Paramètre non reconnu « %s » transmis à la palette de personnages "
+"« %s »."
#: ../folks/alias-details.vala:61
msgid "Alias is not writeable on this contact."
@@ -426,26 +517,28 @@ msgstr "L'alias n'est pas modifiable pour ce contact."
#. Translators: the first parameter is a folder path and the second
#. * is an error message.
-#: ../folks/backend-store.vala:609
+#: ../folks/backend-store.vala:651
#, c-format
msgid "Error listing contents of folder '%s': %s"
-msgstr "Erreur lors de l'énumération du contenu du répertoire « %s » : %s"
+msgstr ""
+"Erreur lors de l'énumération du contenu du répertoire « %s » : %s"
#. Translators: the parameter is a filename.
-#: ../folks/backend-store.vala:739
+#: ../folks/backend-store.vala:786
#, c-format
msgid "File or directory '%s' does not exist."
msgstr "Le fichier ou le répertoire « %s » n'existe pas."
#. Translators: the parameter is a filename.
-#: ../folks/backend-store.vala:745
+#: ../folks/backend-store.vala:792
#, c-format
msgid "Failed to get content type for '%s'."
msgstr "Échec de l'obtention du type de contenu pour « %s »."
#: ../folks/birthday-details.vala:93
msgid "Birthday event ID is not writeable on this contact."
-msgstr "L'ID de l'événement anniversaire n'est pas modifiable pour ce contact."
+msgstr ""
+"L'ID de l'événement anniversaire n'est pas modifiable pour ce contact."
#: ../folks/favourite-details.vala:58
msgid "Favorite status is not writeable on this contact."
@@ -456,47 +549,50 @@ msgstr "Le statut favori n'est pas modifiable pour ce contact."
#: ../folks/im-details.vala:214 ../folks/im-details.vala:241
#, c-format
msgid "The IM address '%s' could not be understood."
-msgstr "L'adresse de messagerie instantanée « %s » n'a pas pu être comprise."
+msgstr ""
+"L'adresse de messagerie instantanée « %s » n'a pas pu être comprise."
#. Translators: the first parameter is a persona store identifier
#. * and the second is an error message.
-#: ../folks/individual-aggregator.vala:921
+#: ../folks/individual-aggregator.vala:1040
#, c-format
msgid "Error preparing persona store '%s': %s"
-msgstr "Erreur lors de la préparation de la palette de personnages « %s » : %s"
+msgstr ""
+"Erreur lors de la préparation de la palette de personnages « %s » : %s"
#. Translators: the parameter is a property name.
-#: ../folks/individual-aggregator.vala:1142
-#: ../folks/individual-aggregator.vala:1368
+#: ../folks/individual-aggregator.vala:1269
+#: ../folks/individual-aggregator.vala:1536
#, c-format
msgid "Unknown property '%s' in linkable property list."
-msgstr "Propriété inconnue « %s » dans la liste de propriétés connectables."
+msgstr ""
+"Propriété inconnue « %s » dans la liste de propriétés connectables."
#. Translators: the first parameter is a store identifier
#. * and the second parameter is an error message.
-#: ../folks/individual-aggregator.vala:1830
+#: ../folks/individual-aggregator.vala:2022
#, c-format
msgid "Failed to add contact for persona store ID '%s': %s"
msgstr ""
"Échec lors de l'ajout du contact pour l'identifiant de la palette de "
"personnages « %s » : %s"
-#: ../folks/individual-aggregator.vala:1931
+#: ../folks/individual-aggregator.vala:2119
msgid "Can’t link personas with no primary store."
msgstr "Impossible de connecter des personnages sans palette principale."
-#: ../folks/individual-aggregator.vala:1932
-#: ../folks/individual-aggregator.vala:2276
+#: ../folks/individual-aggregator.vala:2120
+#: ../folks/individual-aggregator.vala:2451
#, c-format
msgid ""
-"Persona store ‘%s:%s’ is configured as primary, but could not be found or "
-"failed to load."
+"Persona store ‘%s:%s’ is configured as primary, but could not be found "
+"or failed to load."
msgstr ""
-"La palette de personnages « %s:%s » est configurée comme principale, mais "
-"elle n'a pas pu être trouvée ou son chargement a échoué."
+"La palette de personnages « %s:%s » est configurée comme principale, "
+"mais elle n'a pas pu être trouvée ou son chargement a échoué."
-#: ../folks/individual-aggregator.vala:1933
-#: ../folks/individual-aggregator.vala:2277
+#: ../folks/individual-aggregator.vala:2121
+#: ../folks/individual-aggregator.vala:2452
#, c-format
msgid ""
"Check the relevant service is running, or change the default store in that "
@@ -505,32 +601,82 @@ msgstr ""
"Vérifiez que le service pertinent est lancé ou modifiez la palette par "
"défaut dans ce service ou en utilisant la clé GSettings « %s »."
-#: ../folks/individual-aggregator.vala:1965
+#: ../folks/individual-aggregator.vala:2153
msgid "Anti-links can't be removed between personas being linked."
msgstr ""
-"Les anti-liens ne peuvent pas être supprimés entre des personnages qui sont "
-"connectés."
+"Les anti-liens ne peuvent pas être supprimés entre des personnages qui "
+"sont connectés."
-#: ../folks/individual-aggregator.vala:2275
+#: ../folks/individual-aggregator.vala:2450
msgid "Can’t add personas with no primary store."
msgstr "Impossible d'ajouter des personnages sans palette principale."
-#: ../folks/individual-aggregator.vala:2286
+#: ../folks/individual-aggregator.vala:2461
#, c-format
msgid "Can't write to requested property (“%s”) of the writeable store."
msgstr ""
"Impossible d'écrire à la propriété demandée (« %s ») de la palette "
"modifiable."
-#: ../folks/individual.vala:217 ../folks/individual.vala:370
-#: ../folks/individual.vala:479 ../folks/individual.vala:730
-#: ../folks/individual.vala:808
+#: ../folks/individual.vala:216 ../folks/individual.vala:402
+#: ../folks/individual.vala:511 ../folks/individual.vala:762
+#: ../folks/individual.vala:840
#, c-format
msgid "Failed to change property ‘%s’: No suitable personas were found."
msgstr ""
"Échec lors du changement de la propriété « %s » : aucun personnage "
"correspondant trouvé."
+#. Translators: This is the default name for an Individual
+#. * when displayed in the UI if no personal details are available
+#. * for them.
+#: ../folks/individual.vala:1951
+msgid "Unnamed Person"
+msgstr "Personne sans nom"
+
+#. FIXME: Ideally we’d use a format string translated to the locale of the
+#. * persona whose name is being formatted, but no backend provides
+#. * information about personas’ locales, so we have to settle for the
+#. * current user’s locale.
+#. *
+#. * We thought about using nl_langinfo(_NL_NAME_NAME_FMT) here, but
+#. * decided against it because:
+#. * 1. It’s not the best documented API in the world, and its stability
+#. * is in question.
+#. * 2. An attempt to improve the interface in glibc met with a wall of
+#. * complaints: https://sourceware.org/bugzilla/show_bug.cgi?id=14641.
+#. *
+#. * However, we do re-use the string format placeholders from
+#. * _NL_NAME_NAME_FMT (as documented here:
+#. * http://lh.2xlibre.net/values/name_fmt/) because there’s a chance glibc
+#. * might eventually grow a useful interface for this.
+#. *
+#. * It does mean we have to implement our own parser for the name_fmt
+#. * format though, since glibc doesn’t provide a formatting function.
+#. Translators: This is a format string used to convert structured names
+#. * to a single string. It should be translated to the predominant
+#. * semi-formal name format for your locale, using the placeholders
+#. * documented here: http://lh.2xlibre.net/values/name_fmt/. You may be
+#. * able to re-use the existing glibc format string for your locale on that
+#. * page if it’s suitable.
+#. *
+#. * More explicitly: the supported placeholders are %f, %F, %g, %G, %m, %M,
+#. * %t. The romanisation modifier (e.g. %Rf) is recognized but ignored.
+#. * %s, %S and %d are all replaced by the same thing (the ‘Honorific
+#. * Prefixes’ from vCard) so please avoid using more than one.
+#. *
+#. * For example, the format string ‘%g%t%m%t%f’ expands to ‘John Andrew
+#. * Lees’ when used for a persona with first name ‘John’, additional names
+#. * ‘Andrew’ and family names ‘Lees’.
+#. *
+#. * If you need additional placeholders with other information or
+#. * punctuation, please file a bug against libfolks:
+#. * https://bugzilla.gnome.org/enter_bug.cgi?product=folks
+#.
+#: ../folks/name-details.vala:268
+msgid "%g%t%m%t%f"
+msgstr "%g%t%m%t%f"
+
#: ../folks/org.freedesktop.folks.gschema.xml.in.h:1
msgid "Primary store ID"
msgstr "Identifiant de la palette principale"
@@ -539,48 +685,49 @@ msgstr "Identifiant de la palette principale"
msgid ""
"The ID of the persona store which folks should use as primary (i.e. to store "
"linking data in). The type ID of the store may optionally be prepended, "
-"separated by a colon. For example: “eds:system-address-book” or “key-file”."
+"separated by a colon. For example: “eds:system-address-book” or "
+"“key-file”."
msgstr ""
"L'identifiant de la palette de personnages que folks utilise comme "
"principale (c.-à-d. pour y enregistrer les données de connexion). "
"L'identifiant du type de la palette peut être éventuellement ajouté au "
-"début, séparé par deux points. Par exemple : « eds:system-address-book » ou "
-"« key-file »."
+"début, séparé par deux points. Par exemple : "
+"« eds:system-address-book » ou « key-file »."
#: ../folks/postal-address-details.vala:231
#, c-format
msgid "%s, %s, %s, %s, %s, %s, %s"
msgstr "%s, %s, %s, %s, %s, %s, %s"
-#: ../folks/presence-details.vala:159
+#: ../folks/presence-details.vala:171
msgid "Unknown status"
msgstr "Statut inconnu"
-#: ../folks/presence-details.vala:161
+#: ../folks/presence-details.vala:173
msgid "Offline"
msgstr "Hors ligne"
-#: ../folks/presence-details.vala:165
+#: ../folks/presence-details.vala:177
msgid "Error"
msgstr "Erreur"
-#: ../folks/presence-details.vala:167
+#: ../folks/presence-details.vala:179
msgid "Available"
msgstr "Disponible"
-#: ../folks/presence-details.vala:169
+#: ../folks/presence-details.vala:181
msgid "Away"
msgstr "Absent"
-#: ../folks/presence-details.vala:171
+#: ../folks/presence-details.vala:183
msgid "Extended away"
msgstr "Absence prolongée"
-#: ../folks/presence-details.vala:173
+#: ../folks/presence-details.vala:185
msgid "Busy"
msgstr "Occupé"
-#: ../folks/presence-details.vala:175
+#: ../folks/presence-details.vala:187
msgid "Hidden"
msgstr "Masqué"
@@ -612,17 +759,18 @@ msgstr "Le fichier %s n'est pas lisible."
#: ../tools/import-pidgin.vala:82
#, c-format
msgid "The Pidgin buddy list file '%s' could not be loaded."
-msgstr "Le fichier de liste de contacts Pidgin « %s » n'a pas pu être chargé."
+msgstr ""
+"Le fichier de liste de contacts Pidgin « %s » n'a pas pu être chargé."
#. Translators: the parameter is a filename.
#: ../tools/import-pidgin.vala:97
#, c-format
msgid ""
-"The Pidgin buddy list file ‘%s’ could not be loaded: the root element could "
-"not be found or was not recognized."
+"The Pidgin buddy list file ‘%s’ could not be loaded: the root element "
+"could not be found or was not recognized."
msgstr ""
-"Le fichier de liste de contacts Pidgin « %s » n'a pas pu être chargé : "
-"l'élément racine n'a pas pu être retrouvé ou reconnu."
+"Le fichier de liste de contacts Pidgin « %s » n'a pas pu être "
+"chargé : l'élément racine n'a pas pu être retrouvé ou reconnu."
#. Translators: the first parameter is the number of buddies which
#. * were successfully imported, and the second is a filename.
@@ -654,12 +802,13 @@ msgstr ""
#: ../tools/import-pidgin.vala:244
#, c-format
msgid ""
-"Failed to create new contact for buddy with alias ‘%s’ and IM addresses:\n"
+"Failed to create new contact for buddy with alias ‘%s’ and IM "
+"addresses:\n"
"%s\n"
"Error: %s\n"
msgstr ""
-"Impossible de créer le nouveau contact pour l'ami possédant l'alias « %s » "
-"et les adresses de messagerie instantanée : \n"
+"Impossible de créer le nouveau contact pour l'ami possédant l'alias "
+"« %s » et les adresses de messagerie instantanée : \n"
"%s\n"
"Erreur : %s\n"
@@ -672,8 +821,8 @@ msgid ""
"Created contact ‘%s’ for buddy with alias ‘%s’ and IM addresses:\n"
"%s"
msgstr ""
-"Création du contact « %s » pour l'ami possédant l'alias « %s » et les "
-"adresses de messagerie instantanée : \n"
+"Création du contact « %s » pour l'ami possédant l'alias « %s » et "
+"les adresses de messagerie instantanée : \n"
"%s"
#: ../tools/import.vala:44
@@ -684,58 +833,66 @@ msgstr "Nom de moteur source (par défaut : « pidgin »)"
msgid "Source filename (default: specific to source backend)"
msgstr "Nom de fichier source (par défaut : spécifique au moteur source)"
-#: ../tools/import.vala:57
+#: ../tools/import.vala:58
msgid "— import meta-contact information to libfolks"
msgstr "— importer les informations du méta-contact vers libfolks"
#. Translators: the parameter is an error message.
-#: ../tools/import.vala:67
+#: ../tools/import.vala:68
#, c-format
msgid "Couldn't parse command line options: %s"
msgstr "Impossible d'analyser les options de la ligne de commande : %s"
#. Translators: the parameter is an error message.
-#: ../tools/import.vala:108
+#: ../tools/import.vala:109
#, c-format
msgid "Couldn't load the backends: %s"
msgstr "Impossible de charger les moteurs : %s"
#. Translators: the parameter is a backend identifier.
-#: ../tools/import.vala:119
+#: ../tools/import.vala:120
#, c-format
msgid "Couldn't load the ‘%s’ backend."
msgstr "Impossible de charger le moteur « %s »."
#. Translators: the first parameter is a backend identifier and the
#. * second parameter is an error message.
-#: ../tools/import.vala:132
+#: ../tools/import.vala:133
#, c-format
msgid "Couldn't prepare the ‘%s’ backend: %s"
msgstr "Impossible de préparer le moteur « %s » : %s"
#. Translators: the parameter is a backend identifier.
-#: ../tools/import.vala:145
+#: ../tools/import.vala:146
#, c-format
msgid "Couldn't load the ‘%s’ backend's persona store."
msgstr "Impossible de charger la palette de personnages du moteur « %s »."
-#: ../tools/import.vala:166
+#: ../tools/import.vala:167
#, c-format
msgid "Couldn't prepare the ‘%s’ backend's persona store: %s"
-msgstr "Impossible de préparer la palette de personnages du moteur « %s » : %s"
+msgstr ""
+"Impossible de préparer la palette de personnages du moteur « %s » : %s"
#. Translators: the parameter is an error message.
-#: ../tools/import.vala:184
+#: ../tools/import.vala:185
#, c-format
msgid "Error importing contacts: %s"
msgstr "Erreur d'importation de contacts : %s"
#. Translators: both parameters are identifiers for backends.
-#: ../tools/import.vala:198
+#: ../tools/import.vala:199
#, c-format
msgid ""
-"Unrecognized source backend name ‘%s’. ‘%s’ is currently the only supported "
-"source backend."
+"Unrecognized source backend name ‘%s’. ‘%s’ is currently the only "
+"supported source backend."
msgstr ""
-"Nom de moteur source non reconnu « %s ». « %s » est actuellement le seul "
-"moteur source pris en charge."
+"Nom de moteur source non reconnu « %s ». « %s » est actuellement le "
+"seul moteur source pris en charge."
+
+#~ msgid ""
+#~ "Failed to determine whether we can set aliases on Telepathy account '%s': "
+#~ "%s"
+#~ msgstr ""
+#~ "Impossible de déterminer s'il est possible de définir des alias sur le "
+#~ "compte Telepathy « %s » : %s"
diff --git a/po/it.po b/po/it.po
index 23e362f9..ad230dd2 100644
--- a/po/it.po
+++ b/po/it.po
@@ -1,17 +1,17 @@
# Italian translation of Folks
# Copyright (C) 2012
# This file is distributed under the same license as the Folks package.
-# Gianvito Cavasoli <gianvito@gmx.it>, 2012, 2013.
+# Gianvito Cavasoli <gianvito@gmx.it>, 2012, 2013, 2014.
#
msgid ""
msgstr ""
"Project-Id-Version: folks\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?"
"product=folks&keywords=I18N+L10N&component=general\n"
-"POT-Creation-Date: 2013-03-15 10:51+0000\n"
-"PO-Revision-Date: 2013-03-16 14:23+0100\n"
+"POT-Creation-Date: 2014-03-07 05:54+0000\n"
+"PO-Revision-Date: 2014-03-07 11:08+0100\n"
"Last-Translator: Gianvito Cavasoli <gianvito@gmx.it>\n"
-"Language-Team: Italiano <tp@linux.it>\n"
+"Language-Team: Italiano <tp@lists.linux.it>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@@ -19,6 +19,88 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Gtranslator 2.91.6\n"
+#: ../backends/bluez/bluez-backend.vala:600
+msgid ""
+"No BlueZ 5 object manager running, so the BlueZ backend will be inactive. "
+"Either your BlueZ installation is too old (only version 5 is supported) or "
+"the service can’t be started."
+msgstr ""
+"Nessun gestore oggetto BlueZ 5 in esecuzione, così il backend BlueZ sarà "
+"inattivo. L'installazione di BlueZ potrebbe essere troppo vecchia (solo la "
+"versione 5 è supportata) o il servizio non può essere avviato."
+
+#: ../backends/bluez/bluez-backend.vala:613
+msgid ""
+"Error connecting to OBEX transfer daemon over D-Bus. Ensure BlueZ and obexd "
+"are installed."
+msgstr ""
+"Si è verificato un problema nella connessione al demone di trasferimento "
+"OBEX verso D-Bus. Assicurarsi che BlueZ e obexd siano installati."
+
+#. Translators: the parameter is an error message.
+#: ../backends/bluez/bluez-persona-store.vala:385
+#, c-format
+msgid "Error reading the transferred address book file: %s"
+msgstr ""
+"Si è verificato un errore leggendo il file della rubrica trasferita: %s"
+
+#. Translators: the first parameter is the name of the
+#. * failed transfer, and the second is a Bluetooth device
+#. * alias.
+#. Translators: the first parameter is the name of the failed
+#. * transfer, and the second is a Bluetooth device alias.
+#: ../backends/bluez/bluez-persona-store.vala:667
+#: ../backends/bluez/bluez-persona-store.vala:689
+#, c-format
+msgid ""
+"Error during transfer of the address book ‘%s’ from Bluetooth device ‘%s’."
+msgstr ""
+"Si è verificato un errore durante il trasferimento della rubrica «%s» dal "
+"dispositivo Bluetooth «%s»."
+
+#: ../backends/bluez/bluez-persona-store.vala:782
+#, c-format
+msgid ""
+"Permission to access the address book on Bluetooth device ‘%s’ was denied by "
+"the user."
+msgstr ""
+"Il permesso per accedere alla rubrica sul dispositivo Bluetooth «%s» è stato "
+"negato dall'utente."
+
+#. Translators: the first parameter is a Bluetooth device
+#. * alias, and the second is an error message.
+#: ../backends/bluez/bluez-persona-store.vala:789
+#, c-format
+msgid "An OBEX address book transfer from device ‘%s’ could not be started: %s"
+msgstr ""
+"Impossibile avviare il trasferimento OBEX della rubrica dal dispositivo "
+"«%s»: %s"
+
+#. Translators: the first parameter is a Bluetooth device
+#. * alias, and the second is an error message.
+#: ../backends/bluez/bluez-persona-store.vala:829
+#, c-format
+msgid "The OBEX address book transfer from device ‘%s’ failed: %s"
+msgstr ""
+"Il trasferimento OBEX della rubrica dal dispositivo «%s» non è riuscito: %s"
+
+#. Translators: the first parameter is a Bluetooth device
+#. * alias, and the second is an error message.
+#: ../backends/bluez/bluez-persona-store.vala:846
+#, c-format
+msgid ""
+"Error during transfer of the address book from Bluetooth device ‘%s’: %s"
+msgstr ""
+"Si è verificato un errore nel trasferimento della rubrica dal dispositivo "
+"Bluetooth «%s»: %s"
+
+#: ../backends/bluez/bluez-persona-store.vala:1064
+#, c-format
+msgid "Bluetooth device ‘%s’ disappeared during address book transfer."
+msgstr ""
+"Il dispositivo Bluetooth «%s» è scomparso durante il trasferimento della "
+"rubrica."
+
#. The timeout after which we consider a property change to have failed if we
#. * haven't received a property change notification for it.
#. seconds
@@ -33,7 +115,7 @@ msgstr ""
#. Translators: the first parameter is an address book
#. * URI and the second is a persona UID.
-#: ../backends/eds/lib/edsf-persona-store.vala:671
+#: ../backends/eds/lib/edsf-persona-store.vala:673
#, c-format
msgid "Address book ‘%s’ is offline, so contact ‘%s’ cannot be removed."
msgstr ""
@@ -42,62 +124,62 @@ msgstr ""
#. Translators: the first parameter is an address book
#. * URI and the second is an error message.
-#: ../backends/eds/lib/edsf-persona-store.vala:677
+#: ../backends/eds/lib/edsf-persona-store.vala:679
#, c-format
msgid "Permission denied to remove contact ‘%s’: %s"
msgstr "Permesso negato per rimuovere il contatto «%s»: %s"
#. Translators: the parameter is an error message.
-#: ../backends/eds/lib/edsf-persona-store.vala:682
+#: ../backends/eds/lib/edsf-persona-store.vala:684
#, c-format
msgid "Removing contacts isn't supported by this persona store: %s"
msgstr ""
"La rimozione dei contatti non è supportata da questo archivio personale: %s"
-#: ../backends/eds/lib/edsf-persona-store.vala:711
+#: ../backends/eds/lib/edsf-persona-store.vala:713
#, c-format
msgid "Can't remove contact ‘%s’: %s"
msgstr "Impossibile rimuovere il contatto «%s»: %s"
#. Translators: the parameter is an address book
#. * URI.
-#: ../backends/eds/lib/edsf-persona-store.vala:801
-#: ../backends/eds/lib/edsf-persona-store.vala:992
+#: ../backends/eds/lib/edsf-persona-store.vala:802
+#: ../backends/eds/lib/edsf-persona-store.vala:993
#, c-format
msgid "Address book ‘%s’ is offline."
msgstr "La rubrica «%s» non è in rete."
#. Translators: the first parameter is an address
#. * book URI and the second is an error message.
-#: ../backends/eds/lib/edsf-persona-store.vala:806
-#: ../backends/eds/lib/edsf-persona-store.vala:997
+#: ../backends/eds/lib/edsf-persona-store.vala:807
+#: ../backends/eds/lib/edsf-persona-store.vala:998
#, c-format
msgid "Permission denied to open address book ‘%s’: %s"
msgstr "Permesso negato per aprire la rubrica «%s»: %s"
#. Translators: the first parameter is an address book URI
#. * and the second is an error message.
-#: ../backends/eds/lib/edsf-persona-store.vala:839
+#: ../backends/eds/lib/edsf-persona-store.vala:840
#, c-format
msgid "Couldn't open address book ‘%s’: %s"
msgstr "Impossibile aprire la rubrica «%s»: %s"
#. Translators: the parameteter is an error message.
-#: ../backends/eds/lib/edsf-persona-store.vala:905
-#: ../backends/eds/lib/edsf-persona-store.vala:935
+#: ../backends/eds/lib/edsf-persona-store.vala:906
+#: ../backends/eds/lib/edsf-persona-store.vala:936
#, c-format
msgid "Couldn't get address book capabilities: %s"
msgstr "Impossibile ottenere le funzionalità della rubrica: %s"
#. Translators: the parameter is an address book URI.
-#: ../backends/eds/lib/edsf-persona-store.vala:951
+#: ../backends/eds/lib/edsf-persona-store.vala:952
#, c-format
msgid "Couldn't get view for address book ‘%s’."
msgstr "Impossibile ottenere la visualizzazione per la rubrica «%s»"
#. Translators: the first parameter is an address book URI
#. * and the second is an error message.
-#: ../backends/eds/lib/edsf-persona-store.vala:1030
+#: ../backends/eds/lib/edsf-persona-store.vala:1031
#, c-format
msgid "Couldn't get view for address book ‘%s’: %s"
msgstr "Impossibile ottenere la visualizzazione per la rubrica «%s»: %s"
@@ -105,122 +187,122 @@ msgstr "Impossibile ottenere la visualizzazione per la rubrica «%s»: %s"
#. Translators: the parameter is the name of a property on a
#. * contact, formatted in the normal GObject style (e.g.
#. * lowercase with hyphens to separate words).
-#: ../backends/eds/lib/edsf-persona-store.vala:1390
+#: ../backends/eds/lib/edsf-persona-store.vala:1303
#, c-format
msgid "Changing the ‘%s’ property failed due to reaching the timeout."
msgstr ""
"La modifica della proprietà «%s» non è riuscita a causa del tempo scaduto."
-#: ../backends/eds/lib/edsf-persona-store.vala:1428
+#: ../backends/eds/lib/edsf-persona-store.vala:1337
#: ../folks/avatar-details.vala:63
msgid "Avatar is not writeable on this contact."
msgstr "L'avatar non è scrivibile in questo contatto."
-#: ../backends/eds/lib/edsf-persona-store.vala:1449
+#: ../backends/eds/lib/edsf-persona-store.vala:1358
#: ../folks/web-service-details.vala:123
msgid "Web service addresses are not writeable on this contact."
msgstr "Gli indirizzi dei servizi web non sono scrivibili in questo contatto."
-#: ../backends/eds/lib/edsf-persona-store.vala:1485
+#: ../backends/eds/lib/edsf-persona-store.vala:1394
#: ../folks/url-details.vala:152
msgid "URLs are not writeable on this contact."
msgstr "Gli URL non sono scrivibili in questo contatto."
-#: ../backends/eds/lib/edsf-persona-store.vala:1566
+#: ../backends/eds/lib/edsf-persona-store.vala:1475
#: ../folks/local-id-details.vala:64
msgid "Local IDs are not writeable on this contact."
msgstr "Gli ID locali non sono scrivibili in questo contatto."
-#: ../backends/eds/lib/edsf-persona-store.vala:1595
+#: ../backends/eds/lib/edsf-persona-store.vala:1504
msgid "The contact cannot be marked as favourite."
msgstr "Impossibile marcare il contatto come preferito."
#. Translators: the parameter is an error message.
-#: ../backends/eds/lib/edsf-persona-store.vala:1667
+#: ../backends/eds/lib/edsf-persona-store.vala:1576
#, c-format
msgid "Can't update avatar: %s"
msgstr "Impossibile aggiornare l'avatar: %s"
-#: ../backends/eds/lib/edsf-persona-store.vala:1678
+#: ../backends/eds/lib/edsf-persona-store.vala:1587
#: ../folks/email-details.vala:120
msgid "E-mail addresses are not writeable on this contact."
msgstr "Gli indirizzi mail non sono scrivibili in questo contatto."
-#: ../backends/eds/lib/edsf-persona-store.vala:1696
-#: ../folks/phone-details.vala:224
+#: ../backends/eds/lib/edsf-persona-store.vala:1605
+#: ../folks/phone-details.vala:255
msgid "Phone numbers are not writeable on this contact."
msgstr "I numeri di telefono non sono scrivibili in questo contatto."
-#: ../backends/eds/lib/edsf-persona-store.vala:1714
+#: ../backends/eds/lib/edsf-persona-store.vala:1623
#: ../folks/postal-address-details.vala:361
msgid "Postal addresses are not writeable on this contact."
msgstr "Gli indirizzi postali non sono scrivibili in questo contatto."
-#: ../backends/eds/lib/edsf-persona-store.vala:1785
-#: ../folks/name-details.vala:283
+#: ../backends/eds/lib/edsf-persona-store.vala:1694
+#: ../folks/name-details.vala:454
msgid "Full name is not writeable on this contact."
msgstr "Il nome completo non è scrivibile in questo contatto."
-#: ../backends/eds/lib/edsf-persona-store.vala:1807
-#: ../folks/name-details.vala:321
+#: ../backends/eds/lib/edsf-persona-store.vala:1716
+#: ../folks/name-details.vala:492
msgid "Nickname is not writeable on this contact."
msgstr "Il soprannome non è scrivibile in questo contatto."
-#: ../backends/eds/lib/edsf-persona-store.vala:1829
+#: ../backends/eds/lib/edsf-persona-store.vala:1738
#: ../folks/note-details.vala:138
msgid "Notes are not writeable on this contact."
msgstr "Le note non sono scrivibili in questo contatto."
-#: ../backends/eds/lib/edsf-persona-store.vala:1861
+#: ../backends/eds/lib/edsf-persona-store.vala:1770
#: ../folks/birthday-details.vala:62
msgid "Birthday is not writeable on this contact."
msgstr "Il compleanno non è scrivibile in questo contatto."
-#: ../backends/eds/lib/edsf-persona-store.vala:1905
+#: ../backends/eds/lib/edsf-persona-store.vala:1814
#: ../folks/role-details.vala:279
msgid "Roles are not writeable on this contact."
msgstr "I ruoli non sono scrivibili in questo contatto."
-#: ../backends/eds/lib/edsf-persona-store.vala:2006
-#: ../folks/name-details.vala:246
+#: ../backends/eds/lib/edsf-persona-store.vala:1915
+#: ../folks/name-details.vala:417
msgid "Structured name is not writeable on this contact."
msgstr "Il nome strutturato non è scrivibile in questo contatto."
-#: ../backends/eds/lib/edsf-persona-store.vala:2045
+#: ../backends/eds/lib/edsf-persona-store.vala:1954
#: ../folks/im-details.vala:136
msgid "IM addresses are not writeable on this contact."
msgstr ""
"Gli indirizzi di messaggistica istantanea non sono scrivibili in questo "
"contatto."
-#: ../backends/eds/lib/edsf-persona-store.vala:2095
+#: ../backends/eds/lib/edsf-persona-store.vala:2004
#: ../folks/group-details.vala:174
msgid "Groups are not writeable on this contact."
msgstr "I gruppi non sono scrivibili in questo contatto."
-#: ../backends/eds/lib/edsf-persona-store.vala:2110
+#: ../backends/eds/lib/edsf-persona-store.vala:2019
msgid "My Contacts is only available for Google Contacts"
msgstr "Miei contatti è solo disponibile per i Contatti Google"
-#: ../backends/eds/lib/edsf-persona-store.vala:2181
+#: ../backends/eds/lib/edsf-persona-store.vala:2090
#: ../folks/gender-details.vala:79
msgid "Gender is not writeable on this contact."
msgstr "Il sesso non è scrivibile in questo contatto."
-#: ../backends/eds/lib/edsf-persona-store.vala:2219
-#: ../folks/anti-linkable.vala:81
+#: ../backends/eds/lib/edsf-persona-store.vala:2128
+#: ../folks/anti-linkable.vala:84
msgid "Anti-links are not writeable on this contact."
msgstr "Gli anti-links non sono scrivibili in questo contatto."
-#: ../backends/eds/lib/edsf-persona-store.vala:2262
-#: ../folks/location-details.vala:129
+#: ../backends/eds/lib/edsf-persona-store.vala:2171
+#: ../folks/location-details.vala:135
msgid "Location is not writeable on this contact."
msgstr "La posizione non è scrivibile in questo contatto."
#. Translators: the first parameter is a non-human-readable
#. * property name and the second parameter is an error
#. * message.
-#: ../backends/eds/lib/edsf-persona-store.vala:2439
+#: ../backends/eds/lib/edsf-persona-store.vala:2484
#, c-format
msgid "Property ‘%s’ is not writeable: %s"
msgstr "La proprietà «%s» non è scrivibile: %s"
@@ -228,42 +310,42 @@ msgstr "La proprietà «%s» non è scrivibile: %s"
#. Translators: the first parameter is a non-human-readable
#. * property name and the second parameter is an error
#. * message.
-#: ../backends/eds/lib/edsf-persona-store.vala:2448
+#: ../backends/eds/lib/edsf-persona-store.vala:2493
#, c-format
msgid "Invalid value for property ‘%s’: %s"
msgstr "Valore non valido per la proprietà «%s»: %s"
#. Translators: the first parameter is a non-human-readable
#. * property name and the second parameter is an error message.
-#: ../backends/eds/lib/edsf-persona-store.vala:2474
+#: ../backends/eds/lib/edsf-persona-store.vala:2519
#, c-format
msgid "Unknown error setting property ‘%s’: %s"
msgstr "Errore sconosciuto di impostazione della proprietà «%s»: %s"
#. Translators: the first parameter is a filename, and
#. * the second is an error message.
-#: ../backends/key-file/kf-persona-store.vala:233
+#: ../backends/key-file/kf-persona-store.vala:234
#, c-format
msgid "The relationship key file '%s' could not be loaded: %s"
msgstr "La chiave di relazione del file «%s» non può essere caricata: %s"
#. Translators: the first parameter is a path, and the
#. * second is an error message.
-#: ../backends/key-file/kf-persona-store.vala:255
+#: ../backends/key-file/kf-persona-store.vala:256
#, c-format
msgid "The relationship key file directory '%s' could not be created: %s"
msgstr "La chiave di relazione della directory «%s» non può essere creata: %s"
#. Translators: the first parameter is a filename, and
#. * the second is an error message.
-#: ../backends/key-file/kf-persona-store.vala:279
+#: ../backends/key-file/kf-persona-store.vala:280
#, c-format
msgid "The relationship key file '%s' could not be created: %s"
msgstr "La chiave di relazione del file «%s» non può essere creata: %s"
#. Translators: the first parameter is a filename, the second is
#. * an error message.
-#: ../backends/key-file/kf-persona-store.vala:470
+#: ../backends/key-file/kf-persona-store.vala:471
#, c-format
msgid "Could not write updated key file '%s': %s"
msgstr "Impossibile scrivere un file chiave «%s» aggiornato: %s"
@@ -273,7 +355,7 @@ msgstr "Impossibile scrivere un file chiave «%s» aggiornato: %s"
#. * an IM address (e.g. “foo@jabber.org”), the second is
#. * the name of a protocol (e.g. “jabber”) and the third is
#. * an error message.
-#: ../backends/key-file/kf-persona.vala:172
+#: ../backends/key-file/kf-persona.vala:174
#, c-format
msgid "Invalid IM address ‘%s’ for protocol ‘%s’: %s"
msgstr ""
@@ -281,7 +363,7 @@ msgstr ""
"«%s»: %s"
#. Translators: the parameter is an error message.
-#: ../backends/key-file/kf-persona.vala:430
+#: ../backends/key-file/kf-persona.vala:432
#, c-format
msgid "Couldn't load data from key file: %s"
msgstr "Impossibile caricare i dati dal file chiave: %s"
@@ -306,31 +388,29 @@ msgstr "Nessuna funzionalità di contatti è stata trovata."
msgid "Error opening contacts view."
msgstr "Errore nell'apertura della visualizzazione dei contatti."
-#. Translators: the first parameter is the display name for
-#. * the Telepathy account, and the second is an error
-#. * message.
-#: ../backends/telepathy/lib/tpf-persona-store.vala:814
-#, c-format
+#: ../backends/ofono/ofono-backend.vala:196
msgid ""
-"Failed to determine whether we can set aliases on Telepathy account '%s': %s"
+"No oFono object manager running, so the oFono backend will be inactive. "
+"Either oFono isn’t installed or the service can’t be started."
msgstr ""
-"Impossibile determinare se si può impostare degli alias nell'account "
-"Telepathy «%s»: %s"
+"Nessun gestore oggetto oFono in esecuzione, così il backend oFono sarà "
+"inattivo. oFono potrebbe essere non installato o il servizio non può essere "
+"avviato."
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1278
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1248
msgid "Telepathy contacts representing the local user may not be removed."
msgstr ""
"I contatti Telepathy che rappresentano l'utente locale non possono essere "
"rimossi."
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1289
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1259
#, c-format
msgid "Failed to remove a persona from store: %s"
msgstr "Rimozione di un contatto dall'archivio non riuscita: %s"
#. Translators: the first two parameters are store identifiers and
#. * the third is a contact identifier.
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1324
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1294
#, c-format
msgid ""
"Persona store (%s, %s) requires the following details:\n"
@@ -339,19 +419,19 @@ msgstr ""
"L'archivio personale (%s, %s) richiede i seguenti dettagli:\n"
" contatto (fornito da: «%s»)\n"
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1339
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1309
msgid "Cannot create a new Telepathy contact while offline."
msgstr ""
"Impossibile creare un nuovo contatto Telepathy quando non si è in rete."
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1357
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1327
#, c-format
msgid "Failed to add a persona from details: %s"
msgstr "Aggiunta di un profilo dai dettagli non riuscita: %s"
#. Translators: "telepathy-logger" is the name of an application,
#. * and should not be translated.
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1377
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1347
msgid ""
"Failed to change favorite without a connection to the telepathy-logger "
"service."
@@ -359,7 +439,7 @@ msgstr ""
"Modifica dei preferiti non riuscita senza una connessione al servizio "
"telepathy-logger."
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1383
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1353
msgid ""
"Failed to change favorite status of Telepathy Persona because it has no "
"attached TpContact."
@@ -368,50 +448,50 @@ msgstr ""
"non ha allegato TpContact."
#. Translators: the parameter is a contact identifier.
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1401
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1371
#, c-format
msgid "Failed to change favorite status for Telepathy contact ‘%s’."
msgstr ""
"Modifica dello stato di preferito del contatto Telepathy «%s» non riuscita."
#. Translators: the parameter is an error message.
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1433
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1403
#, c-format
msgid "Failed to change contact's alias: %s"
msgstr "Modifica dell'alias del contatto non riuscita: %s"
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1514
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1484
msgid "Extended information may only be set on the user's Telepathy contact."
msgstr ""
"Le informazioni estese possono essere impostate solo sul contatto Telepathy "
"dell'utente."
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1543
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1513
msgid ""
"Extended information cannot be written because the store is disconnected."
msgstr ""
"Le informazioni estese non possono essere scritte perché l'archivio non è "
"connesso."
-#: ../backends/telepathy/lib/tpf-persona.vala:499
-#: ../backends/telepathy/lib/tpf-persona.vala:520
-#: ../backends/telepathy/lib/tpf-persona.vala:572
-#: ../backends/telepathy/lib/tpf-persona.vala:586
+#: ../backends/telepathy/lib/tpf-persona.vala:511
+#: ../backends/telepathy/lib/tpf-persona.vala:532
+#: ../backends/telepathy/lib/tpf-persona.vala:584
+#: ../backends/telepathy/lib/tpf-persona.vala:598
#, c-format
msgid "Failed to change group membership: %s"
msgstr "Cambio di appartenenza a un gruppo non riuscito: %s"
#. Translators: "account" refers to an instant messaging
#. * account.
-#: ../backends/telepathy/lib/tpf-persona.vala:502
-#: ../backends/telepathy/lib/tpf-persona.vala:575
+#: ../backends/telepathy/lib/tpf-persona.vala:514
+#: ../backends/telepathy/lib/tpf-persona.vala:587
msgid "Account is offline."
msgstr "L'account è fuori rete."
#. Translators: the first parameter is the unknown key that
#. * was received with the details params, and the second
#. * identifies the persona store.
-#: ../backends/tracker/lib/trf-persona-store.vala:742
+#: ../backends/tracker/lib/trf-persona-store.vala:743
#, c-format
msgid "Unrecognized parameter '%s' passed to persona store '%s'."
msgstr "Parametro «%s» passato all'archivio personale «%s» non riconosciuto."
@@ -422,19 +502,19 @@ msgstr "L'alias non è scrivibile in questo contatto."
#. Translators: the first parameter is a folder path and the second
#. * is an error message.
-#: ../folks/backend-store.vala:627
+#: ../folks/backend-store.vala:651
#, c-format
msgid "Error listing contents of folder '%s': %s"
msgstr "Errore nell'elencare i contenuti della cartella «%s»: «%s»"
#. Translators: the parameter is a filename.
-#: ../folks/backend-store.vala:757
+#: ../folks/backend-store.vala:786
#, c-format
msgid "File or directory '%s' does not exist."
msgstr "Il file o la directory «%s» non esiste."
#. Translators: the parameter is a filename.
-#: ../folks/backend-store.vala:763
+#: ../folks/backend-store.vala:792
#, c-format
msgid "Failed to get content type for '%s'."
msgstr "Recupero del tipo di contenuto di «%s» non riuscito."
@@ -456,32 +536,32 @@ msgstr "Impossibile riconoscere l'indirizzo di messaggistica istantanea «%s»."
#. Translators: the first parameter is a persona store identifier
#. * and the second is an error message.
-#: ../folks/individual-aggregator.vala:935
+#: ../folks/individual-aggregator.vala:1040
#, c-format
msgid "Error preparing persona store '%s': %s"
msgstr "Errore nella preparazione dell'archivio personale «%s»: %s"
#. Translators: the parameter is a property name.
-#: ../folks/individual-aggregator.vala:1158
-#: ../folks/individual-aggregator.vala:1386
+#: ../folks/individual-aggregator.vala:1269
+#: ../folks/individual-aggregator.vala:1536
#, c-format
msgid "Unknown property '%s' in linkable property list."
msgstr "Proprietà «%s» nell'elenco delle proprietà collegabili sconosciuta."
#. Translators: the first parameter is a store identifier
#. * and the second parameter is an error message.
-#: ../folks/individual-aggregator.vala:1857
+#: ../folks/individual-aggregator.vala:2022
#, c-format
msgid "Failed to add contact for persona store ID '%s': %s"
msgstr ""
"Aggiunta del contatto per l'ID dell'archivio personale «%s» non riuscita: %s"
-#: ../folks/individual-aggregator.vala:1958
+#: ../folks/individual-aggregator.vala:2119
msgid "Can’t link personas with no primary store."
msgstr "Impossibile collegare dei profili senza un archivio primario."
-#: ../folks/individual-aggregator.vala:1959
-#: ../folks/individual-aggregator.vala:2291
+#: ../folks/individual-aggregator.vala:2120
+#: ../folks/individual-aggregator.vala:2451
#, c-format
msgid ""
"Persona store ‘%s:%s’ is configured as primary, but could not be found or "
@@ -490,8 +570,8 @@ msgstr ""
"L'archivio personale «%s:%s» è configurato come primario, ma non può essere "
"trovato oppure il caricamento non è riuscito."
-#: ../folks/individual-aggregator.vala:1960
-#: ../folks/individual-aggregator.vala:2292
+#: ../folks/individual-aggregator.vala:2121
+#: ../folks/individual-aggregator.vala:2452
#, c-format
msgid ""
"Check the relevant service is running, or change the default store in that "
@@ -500,30 +580,80 @@ msgstr ""
"Verificare che il corrispondente servizio sia in esecuzione, o cambiare "
"l'archivio predefinito del servizio o usare la chiave GSettings «%s»."
-#: ../folks/individual-aggregator.vala:1992
+#: ../folks/individual-aggregator.vala:2153
msgid "Anti-links can't be removed between personas being linked."
msgstr ""
"Gli anti-links non possono essere rimossi fra contatti che sono collegati."
-#: ../folks/individual-aggregator.vala:2290
+#: ../folks/individual-aggregator.vala:2450
msgid "Can’t add personas with no primary store."
msgstr "Impossibile aggiungere dei profili senza un archivio primario."
-#: ../folks/individual-aggregator.vala:2301
+#: ../folks/individual-aggregator.vala:2461
#, c-format
msgid "Can't write to requested property (“%s”) of the writeable store."
msgstr ""
"Impossibile scrivere le proprietà richieste («%s») dell'archivio scrivibile."
-#: ../folks/individual.vala:217 ../folks/individual.vala:370
-#: ../folks/individual.vala:479 ../folks/individual.vala:730
-#: ../folks/individual.vala:808
+#: ../folks/individual.vala:216 ../folks/individual.vala:402
+#: ../folks/individual.vala:511 ../folks/individual.vala:762
+#: ../folks/individual.vala:840
#, c-format
msgid "Failed to change property ‘%s’: No suitable personas were found."
msgstr ""
"Modifica della proprietà «%s» non riuscita: nessun profilo adatto è stato "
"trovato."
+#. Translators: This is the default name for an Individual
+#. * when displayed in the UI if no personal details are available
+#. * for them.
+#: ../folks/individual.vala:1951
+msgid "Unnamed Person"
+msgstr "Persona senza nome"
+
+#. FIXME: Ideally we’d use a format string translated to the locale of the
+#. * persona whose name is being formatted, but no backend provides
+#. * information about personas’ locales, so we have to settle for the
+#. * current user’s locale.
+#. *
+#. * We thought about using nl_langinfo(_NL_NAME_NAME_FMT) here, but
+#. * decided against it because:
+#. * 1. It’s not the best documented API in the world, and its stability
+#. * is in question.
+#. * 2. An attempt to improve the interface in glibc met with a wall of
+#. * complaints: https://sourceware.org/bugzilla/show_bug.cgi?id=14641.
+#. *
+#. * However, we do re-use the string format placeholders from
+#. * _NL_NAME_NAME_FMT (as documented here:
+#. * http://lh.2xlibre.net/values/name_fmt/) because there’s a chance glibc
+#. * might eventually grow a useful interface for this.
+#. *
+#. * It does mean we have to implement our own parser for the name_fmt
+#. * format though, since glibc doesn’t provide a formatting function.
+#. Translators: This is a format string used to convert structured names
+#. * to a single string. It should be translated to the predominant
+#. * semi-formal name format for your locale, using the placeholders
+#. * documented here: http://lh.2xlibre.net/values/name_fmt/. You may be
+#. * able to re-use the existing glibc format string for your locale on that
+#. * page if it’s suitable.
+#. *
+#. * More explicitly: the supported placeholders are %f, %F, %g, %G, %m, %M,
+#. * %t. The romanisation modifier (e.g. %Rf) is recognized but ignored.
+#. * %s, %S and %d are all replaced by the same thing (the ‘Honorific
+#. * Prefixes’ from vCard) so please avoid using more than one.
+#. *
+#. * For example, the format string ‘%g%t%m%t%f’ expands to ‘John Andrew
+#. * Lees’ when used for a persona with first name ‘John’, additional names
+#. * ‘Andrew’ and family names ‘Lees’.
+#. *
+#. * If you need additional placeholders with other information or
+#. * punctuation, please file a bug against libfolks:
+#. * https://bugzilla.gnome.org/enter_bug.cgi?product=folks
+#.
+#: ../folks/name-details.vala:268
+msgid "%g%t%m%t%f"
+msgstr "%g%t%m%t%f"
+
#: ../folks/org.freedesktop.folks.gschema.xml.in.h:1
msgid "Primary store ID"
msgstr "ID archivio primario"
@@ -544,35 +674,35 @@ msgstr ""
msgid "%s, %s, %s, %s, %s, %s, %s"
msgstr "%s, %s, %s, %s, %s, %s, %s"
-#: ../folks/presence-details.vala:159
+#: ../folks/presence-details.vala:171
msgid "Unknown status"
msgstr "Stato sconosciuto"
-#: ../folks/presence-details.vala:161
+#: ../folks/presence-details.vala:173
msgid "Offline"
msgstr "Fuori rete"
-#: ../folks/presence-details.vala:165
+#: ../folks/presence-details.vala:177
msgid "Error"
msgstr "Errore"
-#: ../folks/presence-details.vala:167
+#: ../folks/presence-details.vala:179
msgid "Available"
msgstr "Disponibile"
-#: ../folks/presence-details.vala:169
+#: ../folks/presence-details.vala:181
msgid "Away"
msgstr "Assente"
-#: ../folks/presence-details.vala:171
+#: ../folks/presence-details.vala:183
msgid "Extended away"
msgstr "Assenza prolungata"
-#: ../folks/presence-details.vala:173
+#: ../folks/presence-details.vala:185
msgid "Busy"
msgstr "Non disponibile"
-#: ../folks/presence-details.vala:175
+#: ../folks/presence-details.vala:187
msgid "Hidden"
msgstr "Nascosto"
@@ -677,54 +807,54 @@ msgid "Source filename (default: specific to source backend)"
msgstr ""
"Nome del file sorgente (predefinito: specifico per il sorgente del backend)"
-#: ../tools/import.vala:57
+#: ../tools/import.vala:58
msgid "— import meta-contact information to libfolks"
msgstr "— importa in libfolks le informazioni sui meta contatti"
#. Translators: the parameter is an error message.
-#: ../tools/import.vala:67
+#: ../tools/import.vala:68
#, c-format
msgid "Couldn't parse command line options: %s"
msgstr "Impossibile analizzare le opzioni della riga di comando: %s"
#. Translators: the parameter is an error message.
-#: ../tools/import.vala:108
+#: ../tools/import.vala:109
#, c-format
msgid "Couldn't load the backends: %s"
msgstr "Impossibile caricare i backend: %s"
#. Translators: the parameter is a backend identifier.
-#: ../tools/import.vala:119
+#: ../tools/import.vala:120
#, c-format
msgid "Couldn't load the ‘%s’ backend."
msgstr "Impossibile caricare il backend «%s»."
#. Translators: the first parameter is a backend identifier and the
#. * second parameter is an error message.
-#: ../tools/import.vala:132
+#: ../tools/import.vala:133
#, c-format
msgid "Couldn't prepare the ‘%s’ backend: %s"
msgstr "Impossibile preparare il backend «%s»: %s"
#. Translators: the parameter is a backend identifier.
-#: ../tools/import.vala:145
+#: ../tools/import.vala:146
#, c-format
msgid "Couldn't load the ‘%s’ backend's persona store."
msgstr "Impossibile caricare il backend dell'archivio personale «%s»."
-#: ../tools/import.vala:166
+#: ../tools/import.vala:167
#, c-format
msgid "Couldn't prepare the ‘%s’ backend's persona store: %s"
msgstr "Impossibile preparare il backend dell'archivio personale «%s»: %s"
#. Translators: the parameter is an error message.
-#: ../tools/import.vala:184
+#: ../tools/import.vala:185
#, c-format
msgid "Error importing contacts: %s"
msgstr "Errore nell'importazione dei contatti: %s"
#. Translators: both parameters are identifiers for backends.
-#: ../tools/import.vala:198
+#: ../tools/import.vala:199
#, c-format
msgid ""
"Unrecognized source backend name ‘%s’. ‘%s’ is currently the only supported "
diff --git a/po/ko.po b/po/ko.po
index 3e70a81f..613d3648 100644
--- a/po/ko.po
+++ b/po/ko.po
@@ -1,7 +1,7 @@
# Korean translation for folks.
# Copyright (C) 2012, 2013 Seong-ho Cho et al.
# This file is distributed under the same license as the folks package.
-# Seong-ho Cho <darkcircle.0426@gmail.com>, 2012, 2013.
+# Seong-ho Cho <darkcircle.0426@gmail.com>, 2012, 2013, 2014.
#
#
# 참고 :
@@ -12,8 +12,8 @@ msgstr ""
"Project-Id-Version: folks master\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?"
"product=folks&keywords=I18N+L10N&component=general\n"
-"POT-Creation-Date: 2013-03-19 21:58+0000\n"
-"PO-Revision-Date: 2013-03-21 00:01+0900\n"
+"POT-Creation-Date: 2014-03-12 05:54+0000\n"
+"PO-Revision-Date: 2014-03-12 14:59+0900\n"
"Last-Translator: Seong-ho Cho <darkcircle.0426@gmail.com>\n"
"Language-Team: Korean <gnome-kr@googlegroups.com>\n"
"Language: ko\n"
@@ -23,6 +23,77 @@ msgstr ""
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: Poedit 1.5.5\n"
+#: ../backends/bluez/bluez-backend.vala:600
+msgid ""
+"No BlueZ 5 object manager running, so the BlueZ backend will be inactive. "
+"Either your BlueZ installation is too old (only version 5 is supported) or "
+"the service can’t be started."
+msgstr ""
+"BlueZ 5 객체 관리자가 실행중이 아니어서 BlueZ 백엔드를 비활성화합니다. BlueZ "
+"설치가 오래되지 않았는지(버전 5만 지원함), 서비스를 시작할 수 없는지 확인하십"
+"시오."
+
+#: ../backends/bluez/bluez-backend.vala:613
+msgid ""
+"Error connecting to OBEX transfer daemon over D-Bus. Ensure BlueZ and obexd "
+"are installed."
+msgstr ""
+"D-Bus를 통해 OBEX 전송 데몬에 연결하는데 오류가 발생했습니다. BlueZ와 obexd"
+"를 설치했는지 확인하십시오."
+
+#. Translators: the parameter is an error message.
+#: ../backends/bluez/bluez-persona-store.vala:385
+#, c-format
+msgid "Error reading the transferred address book file: %s"
+msgstr "전송한 주소록 파일을 읽는 도중 오류가 발생했습니다: %s"
+
+#. Translators: the first parameter is the name of the
+#. * failed transfer, and the second is a Bluetooth device
+#. * alias.
+#. Translators: the first parameter is the name of the failed
+#. * transfer, and the second is a Bluetooth device alias.
+#: ../backends/bluez/bluez-persona-store.vala:667
+#: ../backends/bluez/bluez-persona-store.vala:689
+#, c-format
+msgid ""
+"Error during transfer of the address book ‘%s’ from Bluetooth device ‘%s’."
+msgstr ""
+"‘%2$s’ 블루투스 장치에서 ‘%1$s’ 주소록을 전송하는 도중 오류가 발생했습니다."
+
+#: ../backends/bluez/bluez-persona-store.vala:782
+#, c-format
+msgid ""
+"Permission to access the address book on Bluetooth device ‘%s’ was denied by "
+"the user."
+msgstr "‘%s’ 블루투스 장치의 주소록 접근 권한을 사용자가 거부했습니다."
+
+#. Translators: the first parameter is a Bluetooth device
+#. * alias, and the second is an error message.
+#: ../backends/bluez/bluez-persona-store.vala:789
+#, c-format
+msgid "An OBEX address book transfer from device ‘%s’ could not be started: %s"
+msgstr "‘%s’ 장치에서 OBEX 주소록 전송을 시작할 수 없습니다: %s"
+
+#. Translators: the first parameter is a Bluetooth device
+#. * alias, and the second is an error message.
+#: ../backends/bluez/bluez-persona-store.vala:829
+#, c-format
+msgid "The OBEX address book transfer from device ‘%s’ failed: %s"
+msgstr "‘%s’ 장치에서 OBEX 주소록 전송에 실패했습니다: %s"
+
+#. Translators: the first parameter is a Bluetooth device
+#. * alias, and the second is an error message.
+#: ../backends/bluez/bluez-persona-store.vala:846
+#, c-format
+msgid ""
+"Error during transfer of the address book from Bluetooth device ‘%s’: %s"
+msgstr "‘%s’ 블루투스 장치에서 주소록을 전송하는 도중 오류가 발생했습니다: %s"
+
+#: ../backends/bluez/bluez-persona-store.vala:1064
+#, c-format
+msgid "Bluetooth device ‘%s’ disappeared during address book transfer."
+msgstr "주소록을 전송하는 도중 ‘%s’ 블루투스 장치가 사라졌습니다."
+
#. The timeout after which we consider a property change to have failed if we
#. * haven't received a property change notification for it.
#. seconds
@@ -37,68 +108,68 @@ msgstr "안드로이드의 즐겨찾기"
#. Translators: the first parameter is an address book
#. * URI and the second is a persona UID.
-#: ../backends/eds/lib/edsf-persona-store.vala:671
+#: ../backends/eds/lib/edsf-persona-store.vala:673
#, c-format
msgid "Address book ‘%s’ is offline, so contact ‘%s’ cannot be removed."
msgstr "‘%s’ 주소록이 오프라인입니다. 따라서 ‘%s’ 연락처를 제거할 수 없습니다."
#. Translators: the first parameter is an address book
#. * URI and the second is an error message.
-#: ../backends/eds/lib/edsf-persona-store.vala:677
+#: ../backends/eds/lib/edsf-persona-store.vala:679
#, c-format
msgid "Permission denied to remove contact ‘%s’: %s"
msgstr "‘%s’ 연락처를 제거할 권한이 거부되었습니다: %s"
#. Translators: the parameter is an error message.
-#: ../backends/eds/lib/edsf-persona-store.vala:682
+#: ../backends/eds/lib/edsf-persona-store.vala:684
#, c-format
msgid "Removing contacts isn't supported by this persona store: %s"
msgstr "이 페르소나 저장소에서 연락처 제거를 지원하지 않습니다: %s"
-#: ../backends/eds/lib/edsf-persona-store.vala:711
+#: ../backends/eds/lib/edsf-persona-store.vala:713
#, c-format
msgid "Can't remove contact ‘%s’: %s"
msgstr "‘%s’ 연락처를 제거할 수 없습니다: %s"
#. Translators: the parameter is an address book
#. * URI.
-#: ../backends/eds/lib/edsf-persona-store.vala:801
-#: ../backends/eds/lib/edsf-persona-store.vala:992
+#: ../backends/eds/lib/edsf-persona-store.vala:802
+#: ../backends/eds/lib/edsf-persona-store.vala:993
#, c-format
msgid "Address book ‘%s’ is offline."
msgstr "‘%s’ 주소록이 오프라인입니다."
#. Translators: the first parameter is an address
#. * book URI and the second is an error message.
-#: ../backends/eds/lib/edsf-persona-store.vala:806
-#: ../backends/eds/lib/edsf-persona-store.vala:997
+#: ../backends/eds/lib/edsf-persona-store.vala:807
+#: ../backends/eds/lib/edsf-persona-store.vala:998
#, c-format
msgid "Permission denied to open address book ‘%s’: %s"
msgstr "‘%s’ 주소록을 열 권한이 거부되었습니다: %s"
#. Translators: the first parameter is an address book URI
#. * and the second is an error message.
-#: ../backends/eds/lib/edsf-persona-store.vala:839
+#: ../backends/eds/lib/edsf-persona-store.vala:840
#, c-format
msgid "Couldn't open address book ‘%s’: %s"
msgstr "‘%s’ 주소록을 열 수 없습니다: %s"
#. Translators: the parameteter is an error message.
-#: ../backends/eds/lib/edsf-persona-store.vala:905
-#: ../backends/eds/lib/edsf-persona-store.vala:935
+#: ../backends/eds/lib/edsf-persona-store.vala:906
+#: ../backends/eds/lib/edsf-persona-store.vala:936
#, c-format
msgid "Couldn't get address book capabilities: %s"
msgstr "주소록 사용 가능 여부를 가져올 수 없습니다: %s"
#. Translators: the parameter is an address book URI.
-#: ../backends/eds/lib/edsf-persona-store.vala:951
+#: ../backends/eds/lib/edsf-persona-store.vala:952
#, c-format
msgid "Couldn't get view for address book ‘%s’."
msgstr "‘%s’ 주소록 보기를 가져올 수 없습니다."
#. Translators: the first parameter is an address book URI
#. * and the second is an error message.
-#: ../backends/eds/lib/edsf-persona-store.vala:1030
+#: ../backends/eds/lib/edsf-persona-store.vala:1031
#, c-format
msgid "Couldn't get view for address book ‘%s’: %s"
msgstr "‘%s’ 주소록 보기를 가져올 수 없습니다: %s"
@@ -106,162 +177,162 @@ msgstr "‘%s’ 주소록 보기를 가져올 수 없습니다: %s"
#. Translators: the parameter is the name of a property on a
#. * contact, formatted in the normal GObject style (e.g.
#. * lowercase with hyphens to separate words).
-#: ../backends/eds/lib/edsf-persona-store.vala:1390
+#: ../backends/eds/lib/edsf-persona-store.vala:1303
#, c-format
msgid "Changing the ‘%s’ property failed due to reaching the timeout."
-msgstr "제한 시간에 도달하여 ‘%s’ 속성을 변경하는데 실패했습니다."
+msgstr "제한 시간에 도달하여 ‘%s’ 속성 값을 바꾸는데 실패했습니다."
-#: ../backends/eds/lib/edsf-persona-store.vala:1428
+#: ../backends/eds/lib/edsf-persona-store.vala:1337
#: ../folks/avatar-details.vala:63
msgid "Avatar is not writeable on this contact."
msgstr "이 연락처에 아바타를 기록할 수 없습니다."
-#: ../backends/eds/lib/edsf-persona-store.vala:1449
+#: ../backends/eds/lib/edsf-persona-store.vala:1358
#: ../folks/web-service-details.vala:123
msgid "Web service addresses are not writeable on this contact."
msgstr "이 연락처에 웹 서비스 주소를 기록할 수 없습니다."
-#: ../backends/eds/lib/edsf-persona-store.vala:1485
+#: ../backends/eds/lib/edsf-persona-store.vala:1394
#: ../folks/url-details.vala:152
msgid "URLs are not writeable on this contact."
msgstr "이 연락처에 URL을 기록할 수 없습니다."
-#: ../backends/eds/lib/edsf-persona-store.vala:1566
+#: ../backends/eds/lib/edsf-persona-store.vala:1475
#: ../folks/local-id-details.vala:64
msgid "Local IDs are not writeable on this contact."
msgstr "이 연락처에 로컬 ID를 기록할 수 없습니다."
-#: ../backends/eds/lib/edsf-persona-store.vala:1595
+#: ../backends/eds/lib/edsf-persona-store.vala:1504
msgid "The contact cannot be marked as favourite."
msgstr "이 연락처를 즐겨찾기로 표시할 수 없습니다."
#. Translators: the parameter is an error message.
-#: ../backends/eds/lib/edsf-persona-store.vala:1667
+#: ../backends/eds/lib/edsf-persona-store.vala:1576
#, c-format
msgid "Can't update avatar: %s"
-msgstr "아바타를 업데이트 할 수 없습니다: %s"
+msgstr "아바타를 업데이트할 수 없습니다: %s"
-#: ../backends/eds/lib/edsf-persona-store.vala:1678
+#: ../backends/eds/lib/edsf-persona-store.vala:1587
#: ../folks/email-details.vala:120
msgid "E-mail addresses are not writeable on this contact."
msgstr "이 연락처에 전자메일 주소를 쓸 수 없습니다."
-#: ../backends/eds/lib/edsf-persona-store.vala:1696
-#: ../folks/phone-details.vala:224
+#: ../backends/eds/lib/edsf-persona-store.vala:1605
+#: ../folks/phone-details.vala:255
msgid "Phone numbers are not writeable on this contact."
msgstr "이 연락처에 전화번호를 쓸 수 없습니다."
-#: ../backends/eds/lib/edsf-persona-store.vala:1714
+#: ../backends/eds/lib/edsf-persona-store.vala:1623
#: ../folks/postal-address-details.vala:361
msgid "Postal addresses are not writeable on this contact."
msgstr "이 연락처에 우편 주소를 쓸 수 없습니다."
-#: ../backends/eds/lib/edsf-persona-store.vala:1785
-#: ../folks/name-details.vala:283
+#: ../backends/eds/lib/edsf-persona-store.vala:1694
+#: ../folks/name-details.vala:454
msgid "Full name is not writeable on this contact."
msgstr "이 연락처에 전체 이름을 쓸 수 없습니다."
-#: ../backends/eds/lib/edsf-persona-store.vala:1807
-#: ../folks/name-details.vala:321
+#: ../backends/eds/lib/edsf-persona-store.vala:1716
+#: ../folks/name-details.vala:492
msgid "Nickname is not writeable on this contact."
msgstr "이 연락처에 닉네임을 쓸 수 없습니다."
-#: ../backends/eds/lib/edsf-persona-store.vala:1829
+#: ../backends/eds/lib/edsf-persona-store.vala:1738
#: ../folks/note-details.vala:138
msgid "Notes are not writeable on this contact."
msgstr "이 연락처에 참고 사항을 쓸 수 없습니다."
-#: ../backends/eds/lib/edsf-persona-store.vala:1861
+#: ../backends/eds/lib/edsf-persona-store.vala:1770
#: ../folks/birthday-details.vala:62
msgid "Birthday is not writeable on this contact."
msgstr "이 연락처에 생일을 쓸 수 없습니다."
-#: ../backends/eds/lib/edsf-persona-store.vala:1905
+#: ../backends/eds/lib/edsf-persona-store.vala:1814
#: ../folks/role-details.vala:279
msgid "Roles are not writeable on this contact."
msgstr "이 연락처에 역할을 쓸 수 없습니다."
-#: ../backends/eds/lib/edsf-persona-store.vala:2006
-#: ../folks/name-details.vala:246
+#: ../backends/eds/lib/edsf-persona-store.vala:1915
+#: ../folks/name-details.vala:417
msgid "Structured name is not writeable on this contact."
msgstr "이 연락처에 구조화된 이름을 쓸 수 없습니다."
-#: ../backends/eds/lib/edsf-persona-store.vala:2045
+#: ../backends/eds/lib/edsf-persona-store.vala:1954
#: ../folks/im-details.vala:136
msgid "IM addresses are not writeable on this contact."
msgstr "이 연락처에 메신저 주소를 쓸 수 없습니다."
-#: ../backends/eds/lib/edsf-persona-store.vala:2095
+#: ../backends/eds/lib/edsf-persona-store.vala:2004
#: ../folks/group-details.vala:174
msgid "Groups are not writeable on this contact."
msgstr "이 연락처에 그룹을 쓸 수 없습니다."
-#: ../backends/eds/lib/edsf-persona-store.vala:2110
+#: ../backends/eds/lib/edsf-persona-store.vala:2019
msgid "My Contacts is only available for Google Contacts"
msgstr "내 연락처는 구글 연락처에서만 사용할 수 있습니다"
-#: ../backends/eds/lib/edsf-persona-store.vala:2181
+#: ../backends/eds/lib/edsf-persona-store.vala:2090
#: ../folks/gender-details.vala:79
msgid "Gender is not writeable on this contact."
msgstr "이 연락처에 성별을 쓸 수 없습니다."
-#: ../backends/eds/lib/edsf-persona-store.vala:2219
-#: ../folks/anti-linkable.vala:81
+#: ../backends/eds/lib/edsf-persona-store.vala:2128
+#: ../folks/anti-linkable.vala:84
msgid "Anti-links are not writeable on this contact."
msgstr "이 연락처에 연결 방지를 쓸 수 없습니다."
-#: ../backends/eds/lib/edsf-persona-store.vala:2262
-#: ../folks/location-details.vala:129
+#: ../backends/eds/lib/edsf-persona-store.vala:2171
+#: ../folks/location-details.vala:135
msgid "Location is not writeable on this contact."
msgstr "이 연락처에 위치를 기록할 수 없습니다."
#. Translators: the first parameter is a non-human-readable
#. * property name and the second parameter is an error
#. * message.
-#: ../backends/eds/lib/edsf-persona-store.vala:2439
+#: ../backends/eds/lib/edsf-persona-store.vala:2484
#, c-format
msgid "Property ‘%s’ is not writeable: %s"
-msgstr "‘%s’ 속성을 쓸 수 없습니다: %s"
+msgstr "‘%s’ 속성 값을 쓸 수 없습니다: %s"
#. Translators: the first parameter is a non-human-readable
#. * property name and the second parameter is an error
#. * message.
-#: ../backends/eds/lib/edsf-persona-store.vala:2448
+#: ../backends/eds/lib/edsf-persona-store.vala:2493
#, c-format
msgid "Invalid value for property ‘%s’: %s"
-msgstr "‘%s’ 속성에 대한 값이 잘못되었습니다: %s"
+msgstr "‘%s’ 속성 값이 잘못되었습니다: %s"
#. Translators: the first parameter is a non-human-readable
#. * property name and the second parameter is an error message.
-#: ../backends/eds/lib/edsf-persona-store.vala:2474
+#: ../backends/eds/lib/edsf-persona-store.vala:2519
#, c-format
msgid "Unknown error setting property ‘%s’: %s"
-msgstr "‘%s’ 속성을 설정하는 중 알 수 없는 오류가 발생했습니다: %s"
+msgstr "‘%s’ 속성 값 설정 도중 알 수 없는 오류가 발생했습니다: %s"
#. Translators: the first parameter is a filename, and
#. * the second is an error message.
-#: ../backends/key-file/kf-persona-store.vala:233
+#: ../backends/key-file/kf-persona-store.vala:234
#, c-format
msgid "The relationship key file '%s' could not be loaded: %s"
msgstr "'%s' 관계 키 파일을 불러올 수 없습니다: %s"
#. Translators: the first parameter is a path, and the
#. * second is an error message.
-#: ../backends/key-file/kf-persona-store.vala:255
+#: ../backends/key-file/kf-persona-store.vala:256
#, c-format
msgid "The relationship key file directory '%s' could not be created: %s"
msgstr "'%s' 관계 키 파일 디렉터리를 만들 수 없습니다: %s"
#. Translators: the first parameter is a filename, and
#. * the second is an error message.
-#: ../backends/key-file/kf-persona-store.vala:279
+#: ../backends/key-file/kf-persona-store.vala:280
#, c-format
msgid "The relationship key file '%s' could not be created: %s"
msgstr "'%s' 관계 키 파일을 만들 수 없습니다: %s"
#. Translators: the first parameter is a filename, the second is
#. * an error message.
-#: ../backends/key-file/kf-persona-store.vala:470
+#: ../backends/key-file/kf-persona-store.vala:471
#, c-format
msgid "Could not write updated key file '%s': %s"
msgstr "업데이트한 '%s' 키 파일에 쓸 수 없습니다: %s"
@@ -271,13 +342,13 @@ msgstr "업데이트한 '%s' 키 파일에 쓸 수 없습니다: %s"
#. * an IM address (e.g. “foo@jabber.org”), the second is
#. * the name of a protocol (e.g. “jabber”) and the third is
#. * an error message.
-#: ../backends/key-file/kf-persona.vala:172
+#: ../backends/key-file/kf-persona.vala:174
#, c-format
msgid "Invalid IM address ‘%s’ for protocol ‘%s’: %s"
-msgstr "‘%2$s’ 프로토콜에 대해 메신저의 ‘%1$s’ 주소가 잘못되었습니다: %3$s"
+msgstr "‘%2$s’ 프로토콜에 대해 ‘%1$s’ 메신저 주소가 잘못되었습니다: %3$s"
#. Translators: the parameter is an error message.
-#: ../backends/key-file/kf-persona.vala:430
+#: ../backends/key-file/kf-persona.vala:432
#, c-format
msgid "Couldn't load data from key file: %s"
msgstr "키 파일로부터 데이터를 불러올 수 없습니다: %s"
@@ -302,27 +373,26 @@ msgstr "사용 가능한 연락처를 찾을 수 없습니다."
msgid "Error opening contacts view."
msgstr "연락처 보기를 여는 중 오류가 발생했습니다."
-#. Translators: the first parameter is the display name for
-#. * the Telepathy account, and the second is an error
-#. * message.
-#: ../backends/telepathy/lib/tpf-persona-store.vala:814
-#, c-format
+#: ../backends/ofono/ofono-backend.vala:196
msgid ""
-"Failed to determine whether we can set aliases on Telepathy account '%s': %s"
-msgstr "'%s' 텔레파시 계정의 별명을 설정할 지 결정하는데 실패했습니다: %s"
+"No oFono object manager running, so the oFono backend will be inactive. "
+"Either oFono isn’t installed or the service can’t be started."
+msgstr ""
+"oFono 객체 관리자가 실행중이 아니어서 oFono 백엔드를 비활성화합니다. oFono를 "
+"설치하지 않았는지, 서비스를 시작할 수 없는지 확인하십시오."
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1278
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1248
msgid "Telepathy contacts representing the local user may not be removed."
-msgstr "로컬 사용자를 표현하는 텔레파시 연락처는 지워지지 않습니다."
+msgstr "로컬 사용자를 나타내는 텔레파시 연락처는 지워지지 않습니다."
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1289
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1259
#, c-format
msgid "Failed to remove a persona from store: %s"
msgstr "저장소에서 페르소나를 제거하는데 실패했습니다: %s"
#. Translators: the first two parameters are store identifiers and
#. * the third is a contact identifier.
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1324
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1294
#, c-format
msgid ""
"Persona store (%s, %s) requires the following details:\n"
@@ -331,18 +401,18 @@ msgstr ""
"페르소나 저장소(%s, %s)에 다음 세부 요소가 필요합니다:\n"
" 연락처(제공: '%s')\n"
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1339
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1309
msgid "Cannot create a new Telepathy contact while offline."
msgstr "오프라인일 때 새 텔레파시 연락처를 만들 수 없습니다."
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1357
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1327
#, c-format
msgid "Failed to add a persona from details: %s"
msgstr "세부 요소로부터 페르소나를 추가하는데 실패했습니다: %s"
#. Translators: "telepathy-logger" is the name of an application,
#. * and should not be translated.
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1377
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1347
msgid ""
"Failed to change favorite without a connection to the telepathy-logger "
"service."
@@ -350,7 +420,7 @@ msgstr ""
"텔레파시 로거 서비스에 연결하지 않은 상태에서 즐겨찾기를 바꾸는데 실패했습니"
"다."
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1383
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1353
msgid ""
"Failed to change favorite status of Telepathy Persona because it has no "
"attached TpContact."
@@ -359,45 +429,45 @@ msgstr ""
"패했습니다."
#. Translators: the parameter is a contact identifier.
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1401
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1371
#, c-format
msgid "Failed to change favorite status for Telepathy contact ‘%s’."
msgstr "‘%s’ 텔레파시 연락처에서 즐겨찾기 상태를 바꾸는데 실패했습니다."
#. Translators: the parameter is an error message.
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1433
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1403
#, c-format
msgid "Failed to change contact's alias: %s"
msgstr "연락처 별명을 바꾸는데 실패했습니다: %s"
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1514
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1484
msgid "Extended information may only be set on the user's Telepathy contact."
msgstr "확장 정보는 사용자의 텔레파시 연락처에만 설정할 수 있습니다."
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1543
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1513
msgid ""
"Extended information cannot be written because the store is disconnected."
msgstr "저장소의 연결이 끊겨서 확장 정보를 쓸 수 없습니다."
-#: ../backends/telepathy/lib/tpf-persona.vala:499
-#: ../backends/telepathy/lib/tpf-persona.vala:520
-#: ../backends/telepathy/lib/tpf-persona.vala:572
-#: ../backends/telepathy/lib/tpf-persona.vala:586
+#: ../backends/telepathy/lib/tpf-persona.vala:511
+#: ../backends/telepathy/lib/tpf-persona.vala:532
+#: ../backends/telepathy/lib/tpf-persona.vala:584
+#: ../backends/telepathy/lib/tpf-persona.vala:598
#, c-format
msgid "Failed to change group membership: %s"
msgstr "그룹 구성원 관계를 바꾸는데 실패했습니다: %s"
#. Translators: "account" refers to an instant messaging
#. * account.
-#: ../backends/telepathy/lib/tpf-persona.vala:502
-#: ../backends/telepathy/lib/tpf-persona.vala:575
+#: ../backends/telepathy/lib/tpf-persona.vala:514
+#: ../backends/telepathy/lib/tpf-persona.vala:587
msgid "Account is offline."
msgstr "계정이 오프라인입니다."
#. Translators: the first parameter is the unknown key that
#. * was received with the details params, and the second
#. * identifies the persona store.
-#: ../backends/tracker/lib/trf-persona-store.vala:742
+#: ../backends/tracker/lib/trf-persona-store.vala:743
#, c-format
msgid "Unrecognized parameter '%s' passed to persona store '%s'."
msgstr "인식할 수 없는 '%s' 매개변수를 페르소나 저장소 '%s'에 전달했습니다."
@@ -408,19 +478,19 @@ msgstr "이 연락처에 별명을 기록할 수 없습니다."
#. Translators: the first parameter is a folder path and the second
#. * is an error message.
-#: ../folks/backend-store.vala:627
+#: ../folks/backend-store.vala:651
#, c-format
msgid "Error listing contents of folder '%s': %s"
msgstr "'%s' 폴더의 내용을 나열하는 중 오류가 발생했습니다: %s"
#. Translators: the parameter is a filename.
-#: ../folks/backend-store.vala:757
+#: ../folks/backend-store.vala:786
#, c-format
msgid "File or directory '%s' does not exist."
-msgstr "'%s' 파일 또는 디렉터리가 존재하지 않습니다."
+msgstr "'%s' 파일 또는 디렉터리가 없습니다."
#. Translators: the parameter is a filename.
-#: ../folks/backend-store.vala:763
+#: ../folks/backend-store.vala:792
#, c-format
msgid "Failed to get content type for '%s'."
msgstr "'%s'에 대한 내용 형식을 가져오는데 실패했습니다."
@@ -442,31 +512,31 @@ msgstr "'%s' 메신저 주소를 인지할 수 없습니다."
#. Translators: the first parameter is a persona store identifier
#. * and the second is an error message.
-#: ../folks/individual-aggregator.vala:935
+#: ../folks/individual-aggregator.vala:1040
#, c-format
msgid "Error preparing persona store '%s': %s"
msgstr "'%s' 페르소나 저장소를 준비하는 중 오류가 발생했습니다: %s"
#. Translators: the parameter is a property name.
-#: ../folks/individual-aggregator.vala:1158
-#: ../folks/individual-aggregator.vala:1386
+#: ../folks/individual-aggregator.vala:1269
+#: ../folks/individual-aggregator.vala:1536
#, c-format
msgid "Unknown property '%s' in linkable property list."
msgstr "연결할 수 있는 속성 목록에서 '%s' 속성을 알 수 없습니다."
#. Translators: the first parameter is a store identifier
#. * and the second parameter is an error message.
-#: ../folks/individual-aggregator.vala:1857
+#: ../folks/individual-aggregator.vala:2022
#, c-format
msgid "Failed to add contact for persona store ID '%s': %s"
msgstr "'%s' 페르소나 저장소 ID에 대한 연락처를 추가하는데 실패했습니다: %s"
-#: ../folks/individual-aggregator.vala:1958
+#: ../folks/individual-aggregator.vala:2119
msgid "Can’t link personas with no primary store."
msgstr "주 저장소 없이는 페르소나에 연결할 수 없습니다."
-#: ../folks/individual-aggregator.vala:1959
-#: ../folks/individual-aggregator.vala:2291
+#: ../folks/individual-aggregator.vala:2120
+#: ../folks/individual-aggregator.vala:2451
#, c-format
msgid ""
"Persona store ‘%s:%s’ is configured as primary, but could not be found or "
@@ -475,8 +545,8 @@ msgstr ""
"‘%s:%s’ 페르소나 저장소를 주 저장소로 설정했지만, 찾을 수 없거나 불러오는데 "
"실패했습니다."
-#: ../folks/individual-aggregator.vala:1960
-#: ../folks/individual-aggregator.vala:2292
+#: ../folks/individual-aggregator.vala:2121
+#: ../folks/individual-aggregator.vala:2452
#, c-format
msgid ""
"Check the relevant service is running, or change the default store in that "
@@ -485,26 +555,78 @@ msgstr ""
"관련 서비스가 실행중인지 확인하거나 서비스의 기본 저장소를 바꾸거나 “%s” "
"GSettings 키를 사용하십시오."
-#: ../folks/individual-aggregator.vala:1992
+#: ../folks/individual-aggregator.vala:2153
msgid "Anti-links can't be removed between personas being linked."
msgstr "연결된 페르소나 사이에서 링크 방지를 제거할 수 없습니다."
-#: ../folks/individual-aggregator.vala:2290
+#: ../folks/individual-aggregator.vala:2450
msgid "Can’t add personas with no primary store."
msgstr "주 저장소에 페르소나를 추가할 수 없습니다."
-#: ../folks/individual-aggregator.vala:2301
+#: ../folks/individual-aggregator.vala:2461
#, c-format
msgid "Can't write to requested property (“%s”) of the writeable store."
msgstr "쓰기 가능한 요청한 속성(“%s”)에 쓸 수 없습니다."
-#: ../folks/individual.vala:217 ../folks/individual.vala:370
-#: ../folks/individual.vala:479 ../folks/individual.vala:730
-#: ../folks/individual.vala:808
+#: ../folks/individual.vala:216 ../folks/individual.vala:402
+#: ../folks/individual.vala:511 ../folks/individual.vala:762
+#: ../folks/individual.vala:840
#, c-format
msgid "Failed to change property ‘%s’: No suitable personas were found."
msgstr "‘%s’ 속성을 바꾸는데 실패했습니다: 적당한 페르소나를 찾지 못했습니다."
+#. Translators: This is the default name for an Individual
+#. * when displayed in the UI if no personal details are available
+#. * for them.
+#: ../folks/individual.vala:1951
+msgid "Unnamed Person"
+msgstr "이름 없는 사용자"
+
+# Note: 한국은 성 이름 중간이름 순으로 가므로 %t를 고려하지 않고
+# %f %g %m 순으로 갑니다. (FIXME 참고)
+#. FIXME: Ideally we’d use a format string translated to the locale of the
+#. * persona whose name is being formatted, but no backend provides
+#. * information about personas’ locales, so we have to settle for the
+#. * current user’s locale.
+#. *
+#. * We thought about using nl_langinfo(_NL_NAME_NAME_FMT) here, but
+#. * decided against it because:
+#. * 1. It’s not the best documented API in the world, and its stability
+#. * is in question.
+#. * 2. An attempt to improve the interface in glibc met with a wall of
+#. * complaints: https://sourceware.org/bugzilla/show_bug.cgi?id=14641.
+#. *
+#. * However, we do re-use the string format placeholders from
+#. * _NL_NAME_NAME_FMT (as documented here:
+#. * http://lh.2xlibre.net/values/name_fmt/) because there’s a chance glibc
+#. * might eventually grow a useful interface for this.
+#. *
+#. * It does mean we have to implement our own parser for the name_fmt
+#. * format though, since glibc doesn’t provide a formatting function.
+#. Translators: This is a format string used to convert structured names
+#. * to a single string. It should be translated to the predominant
+#. * semi-formal name format for your locale, using the placeholders
+#. * documented here: http://lh.2xlibre.net/values/name_fmt/. You may be
+#. * able to re-use the existing glibc format string for your locale on that
+#. * page if it’s suitable.
+#. *
+#. * More explicitly: the supported placeholders are %f, %F, %g, %G, %m, %M,
+#. * %t. The romanisation modifier (e.g. %Rf) is recognized but ignored.
+#. * %s, %S and %d are all replaced by the same thing (the ‘Honorific
+#. * Prefixes’ from vCard) so please avoid using more than one.
+#. *
+#. * For example, the format string ‘%g%t%m%t%f’ expands to ‘John Andrew
+#. * Lees’ when used for a persona with first name ‘John’, additional names
+#. * ‘Andrew’ and family names ‘Lees’.
+#. *
+#. * If you need additional placeholders with other information or
+#. * punctuation, please file a bug against libfolks:
+#. * https://bugzilla.gnome.org/enter_bug.cgi?product=folks
+#.
+#: ../folks/name-details.vala:268
+msgid "%g%t%m%t%f"
+msgstr "%f%t%g%t%m"
+
#: ../folks/org.freedesktop.folks.gschema.xml.in.h:1
msgid "Primary store ID"
msgstr "주 저장소 ID"
@@ -524,35 +646,35 @@ msgstr ""
msgid "%s, %s, %s, %s, %s, %s, %s"
msgstr "%s, %s, %s, %s, %s, %s, %s"
-#: ../folks/presence-details.vala:159
+#: ../folks/presence-details.vala:171
msgid "Unknown status"
msgstr "알 수 없는 상태"
-#: ../folks/presence-details.vala:161
+#: ../folks/presence-details.vala:173
msgid "Offline"
msgstr "오프라인"
-#: ../folks/presence-details.vala:165
+#: ../folks/presence-details.vala:177
msgid "Error"
msgstr "오류"
-#: ../folks/presence-details.vala:167
+#: ../folks/presence-details.vala:179
msgid "Available"
msgstr "자리에 있음"
-#: ../folks/presence-details.vala:169
+#: ../folks/presence-details.vala:181
msgid "Away"
msgstr "자리 비움"
-#: ../folks/presence-details.vala:171
+#: ../folks/presence-details.vala:183
msgid "Extended away"
msgstr "오래 자리 비움"
-#: ../folks/presence-details.vala:173
+#: ../folks/presence-details.vala:185
msgid "Busy"
msgstr "바쁨"
-#: ../folks/presence-details.vala:175
+#: ../folks/presence-details.vala:187
msgid "Hidden"
msgstr "숨김"
@@ -565,7 +687,7 @@ msgstr "직함: %s, 조직: %s, 역할: %s"
#: ../tools/import-pidgin.vala:49
#, c-format
msgid "File %s does not exist."
-msgstr "%s 파일이 존재하지 않습니다."
+msgstr "%s 파일이 없습니다."
#. Translators: the first parameter is a filename, and the second
#. * is an error message.
@@ -652,58 +774,58 @@ msgstr "원본 백엔드 이름(기본값: 'pidgin')"
msgid "Source filename (default: specific to source backend)"
msgstr "원본 파일 이름(기본값: 원본 백엔드로 지정)"
-#: ../tools/import.vala:57
+#: ../tools/import.vala:58
msgid "— import meta-contact information to libfolks"
msgstr "— 메타 연락처 정보를 libforks로 가져옵니다"
#. Translators: the parameter is an error message.
-#: ../tools/import.vala:67
+#: ../tools/import.vala:68
#, c-format
msgid "Couldn't parse command line options: %s"
msgstr "명령줄 옵션을 해석할 수 없습니다: %s"
#. Translators: the parameter is an error message.
-#: ../tools/import.vala:108
+#: ../tools/import.vala:109
#, c-format
msgid "Couldn't load the backends: %s"
msgstr "백엔드를 불러올 수 없습니다: %s"
#. Translators: the parameter is a backend identifier.
-#: ../tools/import.vala:119
+#: ../tools/import.vala:120
#, c-format
msgid "Couldn't load the ‘%s’ backend."
msgstr "‘%s’ 백엔드를 불러올 수 없습니다."
#. Translators: the first parameter is a backend identifier and the
#. * second parameter is an error message.
-#: ../tools/import.vala:132
+#: ../tools/import.vala:133
#, c-format
msgid "Couldn't prepare the ‘%s’ backend: %s"
msgstr "‘%s’ 백엔드를 준비할 수 없습니다: %s"
#. Translators: the parameter is a backend identifier.
-#: ../tools/import.vala:145
+#: ../tools/import.vala:146
#, c-format
msgid "Couldn't load the ‘%s’ backend's persona store."
msgstr "‘%s’ 백엔드의 페르소나 저장소를 불러올 수 없습니다."
-#: ../tools/import.vala:166
+#: ../tools/import.vala:167
#, c-format
msgid "Couldn't prepare the ‘%s’ backend's persona store: %s"
msgstr "‘%s’ 백엔드의 페르소나 저장소를 준비할 수 없습니다: %s"
#. Translators: the parameter is an error message.
-#: ../tools/import.vala:184
+#: ../tools/import.vala:185
#, c-format
msgid "Error importing contacts: %s"
msgstr "연락처를 가져오는 중 오류가 발생했습니다: %s"
#. Translators: both parameters are identifiers for backends.
-#: ../tools/import.vala:198
+#: ../tools/import.vala:199
#, c-format
msgid ""
"Unrecognized source backend name ‘%s’. ‘%s’ is currently the only supported "
"source backend."
msgstr ""
-"‘%s’ 백엔드 이름을 인식할 수 없습니다. ‘%s’은(는) 현재 원본 백엔드만 지원합"
-"니다."
+"‘%s’ 원본 백엔드 이름을 인식할 수 없습니다. ‘%s’은(는) 현재 원본 백엔드만 지"
+"원합니다."
diff --git a/po/lv.po b/po/lv.po
index b2a426e2..ef2adf9b 100644
--- a/po/lv.po
+++ b/po/lv.po
@@ -3,14 +3,14 @@
# This file is distributed under the same license as the folks package.
#
# Arvis Lacis <arvis.lacis@gmail.com>, 2012.
-# Rūdolfs Mazurs <rudolfs.mazurs@gmail.com>, 2012, 2013.
+# Rūdolfs Mazurs <rudolfs.mazurs@gmail.com>, 2012, 2013, 2014.
msgid ""
msgstr ""
"Project-Id-Version: folks master\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?"
"product=folks&keywords=I18N+L10N&component=general\n"
-"POT-Creation-Date: 2013-02-20 14:29+0000\n"
-"PO-Revision-Date: 2013-03-17 20:26+0200\n"
+"POT-Creation-Date: 2014-03-07 05:54+0000\n"
+"PO-Revision-Date: 2014-03-07 21:57+0200\n"
"Last-Translator: Rūdolfs Mazurs <rudolfs.mazurs@gmail.com>\n"
"Language-Team: Latvian <lata-l10n@googlegroups.com>\n"
"Language: lv\n"
@@ -19,7 +19,77 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : "
"2);\n"
-"X-Generator: Lokalize 1.4\n"
+"X-Generator: Lokalize 1.5\n"
+
+#: ../backends/bluez/bluez-backend.vala:600
+msgid ""
+"No BlueZ 5 object manager running, so the BlueZ backend will be inactive. "
+"Either your BlueZ installation is too old (only version 5 is supported) or "
+"the service can’t be started."
+msgstr ""
+"Pašlaik darbojas BlueZ 5 objektu pārvaldnieks, tāpēc BlueZ aizmugure būs "
+"neaktīva. Vai nu jūsu BlueZ instalācija ir pārāk veca (ir atbalstīta tikai 5. "
+"versija), vai arī pakalpojumu nevar palaist."
+
+#: ../backends/bluez/bluez-backend.vala:613
+msgid ""
+"Error connecting to OBEX transfer daemon over D-Bus. Ensure BlueZ and obexd "
+"are installed."
+msgstr ""
+"Kļūda, savienojoties ar OBEX pārsūtīšanas dēmonu, izmantojot D-Bus. "
+"Pārliecinieties, ka ir uzinstalēti BlueZ un obexd."
+
+#. Translators: the parameter is an error message.
+#: ../backends/bluez/bluez-persona-store.vala:385
+#, c-format
+msgid "Error reading the transferred address book file: %s"
+msgstr "Kļūda, lasot pārsūtīto adrešu grāmatas datni — %s"
+
+#. Translators: the first parameter is the name of the
+#. * failed transfer, and the second is a Bluetooth device
+#. * alias.
+#. Translators: the first parameter is the name of the failed
+#. * transfer, and the second is a Bluetooth device alias.
+#: ../backends/bluez/bluez-persona-store.vala:667
+#: ../backends/bluez/bluez-persona-store.vala:689
+#, c-format
+msgid ""
+"Error during transfer of the address book ‘%s’ from Bluetooth device ‘%s’."
+msgstr "Kļūda, pārsūtot adrešu grāmatu “%s” no Bluetooth ierīces “%s”."
+
+#: ../backends/bluez/bluez-persona-store.vala:782
+#, c-format
+msgid ""
+"Permission to access the address book on Bluetooth device ‘%s’ was denied by "
+"the user."
+msgstr "Lietotājs liedza piekļuvi adrešu grāmatai uz “%s” Bluetooth ierīces."
+
+#. Translators: the first parameter is a Bluetooth device
+#. * alias, and the second is an error message.
+#: ../backends/bluez/bluez-persona-store.vala:789
+#, c-format
+msgid "An OBEX address book transfer from device ‘%s’ could not be started: %s"
+msgstr "Nevarēja sākt OBEX adrešu grāmatas pārsūtīšanu no ierīces “%s” — %s"
+
+#. Translators: the first parameter is a Bluetooth device
+#. * alias, and the second is an error message.
+#: ../backends/bluez/bluez-persona-store.vala:829
+#, c-format
+msgid "The OBEX address book transfer from device ‘%s’ failed: %s"
+msgstr "Neizdevās veikt OBEX adrešu grāmatas pārsūtīšanu no ierīces “%s” — %s"
+
+#. Translators: the first parameter is a Bluetooth device
+#. * alias, and the second is an error message.
+#: ../backends/bluez/bluez-persona-store.vala:846
+#, c-format
+msgid ""
+"Error during transfer of the address book from Bluetooth device ‘%s’: %s"
+msgstr "Kļūda, pārsūtot adrešu grāmatu no “%s” Bluetooth ierīces — %s"
+
+#: ../backends/bluez/bluez-persona-store.vala:1064
+#, c-format
+msgid "Bluetooth device ‘%s’ disappeared during address book transfer."
+msgstr "Pārsūtot adrešu grāmatu, pazuda “%s” Bluetooth ierīce."
#. The timeout after which we consider a property change to have failed if we
#. * haven't received a property change notification for it.
@@ -35,68 +105,68 @@ msgstr "Atzīmēts Android"
#. Translators: the first parameter is an address book
#. * URI and the second is a persona UID.
-#: ../backends/eds/lib/edsf-persona-store.vala:671
+#: ../backends/eds/lib/edsf-persona-store.vala:673
#, c-format
msgid "Address book ‘%s’ is offline, so contact ‘%s’ cannot be removed."
msgstr "Adrešu grāmata “%s” ir bezsaistē, tādēļ kontaktu “%s” nevar izņemt."
#. Translators: the first parameter is an address book
#. * URI and the second is an error message.
-#: ../backends/eds/lib/edsf-persona-store.vala:677
+#: ../backends/eds/lib/edsf-persona-store.vala:679
#, c-format
msgid "Permission denied to remove contact ‘%s’: %s"
msgstr "Piekļuve liegta, lai izņemtu kontaktu “%s” — %s"
#. Translators: the parameter is an error message.
-#: ../backends/eds/lib/edsf-persona-store.vala:682
+#: ../backends/eds/lib/edsf-persona-store.vala:684
#, c-format
msgid "Removing contacts isn't supported by this persona store: %s"
msgstr "Kontaktu izņemšana nav atbalstīta šai personu krātuvei — %s"
-#: ../backends/eds/lib/edsf-persona-store.vala:711
+#: ../backends/eds/lib/edsf-persona-store.vala:713
#, c-format
msgid "Can't remove contact ‘%s’: %s"
msgstr "Nevar izņemt kontaktu “%s” — %s"
#. Translators: the parameter is an address book
#. * URI.
-#: ../backends/eds/lib/edsf-persona-store.vala:801
-#: ../backends/eds/lib/edsf-persona-store.vala:992
+#: ../backends/eds/lib/edsf-persona-store.vala:802
+#: ../backends/eds/lib/edsf-persona-store.vala:993
#, c-format
msgid "Address book ‘%s’ is offline."
msgstr "Adrešu grāmata “%s” ir bezsaistē."
#. Translators: the first parameter is an address
#. * book URI and the second is an error message.
-#: ../backends/eds/lib/edsf-persona-store.vala:806
-#: ../backends/eds/lib/edsf-persona-store.vala:997
+#: ../backends/eds/lib/edsf-persona-store.vala:807
+#: ../backends/eds/lib/edsf-persona-store.vala:998
#, c-format
msgid "Permission denied to open address book ‘%s’: %s"
msgstr "Liegta piekļuve atvērt adrešu grāmatu “%s” — %s"
#. Translators: the first parameter is an address book URI
#. * and the second is an error message.
-#: ../backends/eds/lib/edsf-persona-store.vala:839
+#: ../backends/eds/lib/edsf-persona-store.vala:840
#, c-format
msgid "Couldn't open address book ‘%s’: %s"
msgstr "Neizdevās atvērt adrešu grāmatu “%s” — %s"
#. Translators: the parameteter is an error message.
-#: ../backends/eds/lib/edsf-persona-store.vala:905
-#: ../backends/eds/lib/edsf-persona-store.vala:935
+#: ../backends/eds/lib/edsf-persona-store.vala:906
+#: ../backends/eds/lib/edsf-persona-store.vala:936
#, c-format
msgid "Couldn't get address book capabilities: %s"
msgstr "Nevarēja saņemt adrešu grāmatas iespējas — %s"
#. Translators: the parameter is an address book URI.
-#: ../backends/eds/lib/edsf-persona-store.vala:951
+#: ../backends/eds/lib/edsf-persona-store.vala:952
#, c-format
msgid "Couldn't get view for address book ‘%s’."
msgstr "Neizdevās iegūt skatu adrešu grāmatai “%s”."
#. Translators: the first parameter is an address book URI
#. * and the second is an error message.
-#: ../backends/eds/lib/edsf-persona-store.vala:1030
+#: ../backends/eds/lib/edsf-persona-store.vala:1031
#, c-format
msgid "Couldn't get view for address book ‘%s’: %s"
msgstr "Neizdevās iegūt skatu adrešu grāmatai “%s” — %s"
@@ -104,120 +174,119 @@ msgstr "Neizdevās iegūt skatu adrešu grāmatai “%s” — %s"
#. Translators: the parameter is the name of a property on a
#. * contact, formatted in the normal GObject style (e.g.
#. * lowercase with hyphens to separate words).
-#: ../backends/eds/lib/edsf-persona-store.vala:1390
+#: ../backends/eds/lib/edsf-persona-store.vala:1303
#, c-format
msgid "Changing the ‘%s’ property failed due to reaching the timeout."
msgstr "Neizdevās izmainīt “%s” īpašību, jo tika sasniegts taimauts."
-#: ../backends/eds/lib/edsf-persona-store.vala:1428
+#: ../backends/eds/lib/edsf-persona-store.vala:1337
#: ../folks/avatar-details.vala:63
msgid "Avatar is not writeable on this contact."
msgstr "Iemiesojums nav rakstāms šim kontaktam."
-#: ../backends/eds/lib/edsf-persona-store.vala:1449
+#: ../backends/eds/lib/edsf-persona-store.vala:1358
#: ../folks/web-service-details.vala:123
msgid "Web service addresses are not writeable on this contact."
msgstr "Tīkla servisu adreses nav rakstāmas šim kontaktam."
-#: ../backends/eds/lib/edsf-persona-store.vala:1485
+#: ../backends/eds/lib/edsf-persona-store.vala:1394
#: ../folks/url-details.vala:152
msgid "URLs are not writeable on this contact."
msgstr "URL saites nav rakstāmas šim kontaktam."
-#: ../backends/eds/lib/edsf-persona-store.vala:1566
+#: ../backends/eds/lib/edsf-persona-store.vala:1475
#: ../folks/local-id-details.vala:64
msgid "Local IDs are not writeable on this contact."
msgstr "Lokālie ID nav rakstāmi šim kontaktam."
-#: ../backends/eds/lib/edsf-persona-store.vala:1595
+#: ../backends/eds/lib/edsf-persona-store.vala:1504
msgid "The contact cannot be marked as favourite."
msgstr "Šo kontaktu nevar atzīmēt kā iecienītu."
#. Translators: the parameter is an error message.
-#: ../backends/eds/lib/edsf-persona-store.vala:1667
+#: ../backends/eds/lib/edsf-persona-store.vala:1576
#, c-format
msgid "Can't update avatar: %s"
msgstr "Nevar atjaunināt iemiesojumu — %s"
-#: ../backends/eds/lib/edsf-persona-store.vala:1678
+#: ../backends/eds/lib/edsf-persona-store.vala:1587
#: ../folks/email-details.vala:120
msgid "E-mail addresses are not writeable on this contact."
msgstr "E-pasta adreses nav rakstāmas šim kontaktam."
-#: ../backends/eds/lib/edsf-persona-store.vala:1696
-#: ../folks/phone-details.vala:224
+#: ../backends/eds/lib/edsf-persona-store.vala:1605
+#: ../folks/phone-details.vala:255
msgid "Phone numbers are not writeable on this contact."
msgstr "Tālruņa numuri nav rakstāmi šim kontaktam."
-#: ../backends/eds/lib/edsf-persona-store.vala:1714
+#: ../backends/eds/lib/edsf-persona-store.vala:1623
#: ../folks/postal-address-details.vala:361
msgid "Postal addresses are not writeable on this contact."
msgstr "Pasta adreses nav rakstāmas šim kontaktam."
-#: ../backends/eds/lib/edsf-persona-store.vala:1785
-#: ../folks/name-details.vala:283
+#: ../backends/eds/lib/edsf-persona-store.vala:1694
+#: ../folks/name-details.vala:454
msgid "Full name is not writeable on this contact."
msgstr "Pilns vārds nav rakstāms šim kontaktam."
-#: ../backends/eds/lib/edsf-persona-store.vala:1807
-#: ../folks/name-details.vala:321
+#: ../backends/eds/lib/edsf-persona-store.vala:1716
+#: ../folks/name-details.vala:492
msgid "Nickname is not writeable on this contact."
msgstr "Segvārds nav rakstāms šim kontaktam."
-#: ../backends/eds/lib/edsf-persona-store.vala:1829
+#: ../backends/eds/lib/edsf-persona-store.vala:1738
#: ../folks/note-details.vala:138
msgid "Notes are not writeable on this contact."
msgstr "Piezīmes nav rakstāmas šim kontaktam."
-#: ../backends/eds/lib/edsf-persona-store.vala:1861
+#: ../backends/eds/lib/edsf-persona-store.vala:1770
#: ../folks/birthday-details.vala:62
msgid "Birthday is not writeable on this contact."
msgstr "Dzimšanas diena nav rakstāma šim kontaktam."
-#: ../backends/eds/lib/edsf-persona-store.vala:1905
+#: ../backends/eds/lib/edsf-persona-store.vala:1814
#: ../folks/role-details.vala:279
msgid "Roles are not writeable on this contact."
msgstr "Lomas nav rakstāmas šim kontaktam."
-#: ../backends/eds/lib/edsf-persona-store.vala:2006
-#: ../folks/name-details.vala:246
+#: ../backends/eds/lib/edsf-persona-store.vala:1915
+#: ../folks/name-details.vala:417
msgid "Structured name is not writeable on this contact."
msgstr "Strukturētais vārds nav rakstāms šim kontaktam."
-#: ../backends/eds/lib/edsf-persona-store.vala:2045
+#: ../backends/eds/lib/edsf-persona-store.vala:1954
#: ../folks/im-details.vala:136
msgid "IM addresses are not writeable on this contact."
msgstr "TZ adreses nav rakstāmas šim kontaktam."
-#: ../backends/eds/lib/edsf-persona-store.vala:2095
+#: ../backends/eds/lib/edsf-persona-store.vala:2004
#: ../folks/group-details.vala:174
msgid "Groups are not writeable on this contact."
msgstr "Grupas nav rakstāmas šim kontaktam."
-#: ../backends/eds/lib/edsf-persona-store.vala:2110
+#: ../backends/eds/lib/edsf-persona-store.vala:2019
msgid "My Contacts is only available for Google Contacts"
msgstr "Mani kontakti ir pieejami tikai Google kontaktiem"
-#: ../backends/eds/lib/edsf-persona-store.vala:2181
+#: ../backends/eds/lib/edsf-persona-store.vala:2090
#: ../folks/gender-details.vala:79
msgid "Gender is not writeable on this contact."
msgstr "Dzimums nav rakstāms šim kontaktam."
-#: ../backends/eds/lib/edsf-persona-store.vala:2219
-#: ../folks/anti-linkable.vala:81
+#: ../backends/eds/lib/edsf-persona-store.vala:2128
+#: ../folks/anti-linkable.vala:84
msgid "Anti-links are not writeable on this contact."
msgstr "Anti-saites nav rakstāmas šim kontaktam."
-#: ../backends/eds/lib/edsf-persona-store.vala:2262
-#: ../folks/location-details.vala:129
-#| msgid "Avatar is not writeable on this contact."
+#: ../backends/eds/lib/edsf-persona-store.vala:2171
+#: ../folks/location-details.vala:135
msgid "Location is not writeable on this contact."
msgstr "Atrašanās vieta nav rakstāma šim kontaktam."
#. Translators: the first parameter is a non-human-readable
#. * property name and the second parameter is an error
#. * message.
-#: ../backends/eds/lib/edsf-persona-store.vala:2439
+#: ../backends/eds/lib/edsf-persona-store.vala:2484
#, c-format
msgid "Property ‘%s’ is not writeable: %s"
msgstr "Īpašība “%s” nav rakstāma — %s"
@@ -225,42 +294,42 @@ msgstr "Īpašība “%s” nav rakstāma — %s"
#. Translators: the first parameter is a non-human-readable
#. * property name and the second parameter is an error
#. * message.
-#: ../backends/eds/lib/edsf-persona-store.vala:2448
+#: ../backends/eds/lib/edsf-persona-store.vala:2493
#, c-format
msgid "Invalid value for property ‘%s’: %s"
msgstr "Nederīga vērtība īpašībai “%s” — %s"
#. Translators: the first parameter is a non-human-readable
#. * property name and the second parameter is an error message.
-#: ../backends/eds/lib/edsf-persona-store.vala:2474
+#: ../backends/eds/lib/edsf-persona-store.vala:2519
#, c-format
msgid "Unknown error setting property ‘%s’: %s"
msgstr "Nezināma kļūda, iestatot īpašību “%s” — %s"
#. Translators: the first parameter is a filename, and
#. * the second is an error message.
-#: ../backends/key-file/kf-persona-store.vala:233
+#: ../backends/key-file/kf-persona-store.vala:234
#, c-format
msgid "The relationship key file '%s' could not be loaded: %s"
msgstr "Attiecību atslēgu datni “%s” neizdevās ielādēt — %s"
#. Translators: the first parameter is a path, and the
#. * second is an error message.
-#: ../backends/key-file/kf-persona-store.vala:255
+#: ../backends/key-file/kf-persona-store.vala:256
#, c-format
msgid "The relationship key file directory '%s' could not be created: %s"
msgstr "Neizdevās izveidot attiecību atslēgas datnes direktoriju “%s” — %s"
#. Translators: the first parameter is a filename, and
#. * the second is an error message.
-#: ../backends/key-file/kf-persona-store.vala:279
+#: ../backends/key-file/kf-persona-store.vala:280
#, c-format
msgid "The relationship key file '%s' could not be created: %s"
msgstr "Neizdevās izveidot attiecību atslēgas datni “%s” — %s"
#. Translators: the first parameter is a filename, the second is
#. * an error message.
-#: ../backends/key-file/kf-persona-store.vala:470
+#: ../backends/key-file/kf-persona-store.vala:471
#, c-format
msgid "Could not write updated key file '%s': %s"
msgstr "Neizdevās ierakstīt atjaunināto atslēgas datni “%s” — %s"
@@ -270,13 +339,13 @@ msgstr "Neizdevās ierakstīt atjaunināto atslēgas datni “%s” — %s"
#. * an IM address (e.g. “foo@jabber.org”), the second is
#. * the name of a protocol (e.g. “jabber”) and the third is
#. * an error message.
-#: ../backends/key-file/kf-persona.vala:172
+#: ../backends/key-file/kf-persona.vala:174
#, c-format
msgid "Invalid IM address ‘%s’ for protocol ‘%s’: %s"
msgstr "Nederīga TZ adrese “%s” protokolam “%s” — %s"
#. Translators: the parameter is an error message.
-#: ../backends/key-file/kf-persona.vala:430
+#: ../backends/key-file/kf-persona.vala:432
#, c-format
msgid "Couldn't load data from key file: %s"
msgstr "Neizdevās ielādēt datus no atslēgas datnes — %s"
@@ -301,28 +370,26 @@ msgstr "Netika atrastas kontakta iespējas."
msgid "Error opening contacts view."
msgstr "Kļūda, atverot kontaktu skatu."
-#. Translators: the first parameter is the display name for
-#. * the Telepathy account, and the second is an error
-#. * message.
-#: ../backends/telepathy/lib/tpf-persona-store.vala:814
-#, c-format
+#: ../backends/ofono/ofono-backend.vala:196
msgid ""
-"Failed to determine whether we can set aliases on Telepathy account '%s': %s"
+"No oFono object manager running, so the oFono backend will be inactive. "
+"Either oFono isn’t installed or the service can’t be started."
msgstr ""
-"Neizdevās noteikt, vai var iestatīt aizstājvārdus Telepathy kontā “%s” — %s"
+"Pašlaik darbojas oFono objektu pārvaldnieks, tāpēc oFono būs neaktīvs. Vai nu "
+"oFono nav instalēts, vai arī pakalpojumu nevar palaist.\t"
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1278
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1248
msgid "Telepathy contacts representing the local user may not be removed."
msgstr "Nevar izņemt Telepathy kontaktus, kuri pārstāv lokālo lietotāju."
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1289
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1259
#, c-format
msgid "Failed to remove a persona from store: %s"
msgstr "Neizdevās izņemt personu no krātuves — %s"
#. Translators: the first two parameters are store identifiers and
#. * the third is a contact identifier.
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1324
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1294
#, c-format
msgid ""
"Persona store (%s, %s) requires the following details:\n"
@@ -331,25 +398,25 @@ msgstr ""
"Personas krātuvei (%s, %s) ir nepieciešamas sekojošā informācija:\n"
" kontakts (nodrošināts — “%s”)\n"
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1339
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1309
msgid "Cannot create a new Telepathy contact while offline."
msgstr "Nevar izveidot jaunu Telepathy kontaktu, kamēr atrodas bezsaistē."
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1357
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1327
#, c-format
msgid "Failed to add a persona from details: %s"
msgstr "Neizdevās pievienot personu no informācijas — %s"
#. Translators: "telepathy-logger" is the name of an application,
#. * and should not be translated.
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1377
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1347
msgid ""
"Failed to change favorite without a connection to the telepathy-logger "
"service."
msgstr ""
"Neizdevās izmainīt iecienīto bez savienojuma ar telepathy-logger servisu."
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1383
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1353
msgid ""
"Failed to change favorite status of Telepathy Persona because it has no "
"attached TpContact."
@@ -358,45 +425,45 @@ msgstr ""
"pievienota TpContact."
#. Translators: the parameter is a contact identifier.
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1401
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1371
#, c-format
msgid "Failed to change favorite status for Telepathy contact ‘%s’."
msgstr "Neizdevās izmainīt iecienītā statusu Telepathy kontaktam “%s”."
#. Translators: the parameter is an error message.
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1433
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1403
#, c-format
msgid "Failed to change contact's alias: %s"
msgstr "Neizdevās izmainīt kontakta segvārdu — %s"
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1513
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1484
msgid "Extended information may only be set on the user's Telepathy contact."
msgstr "Paplašinātu informāciju var iestatīt tikai Telepathy kontaktiem."
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1542
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1513
msgid ""
"Extended information cannot be written because the store is disconnected."
msgstr "Paplašināto informāciju nevar ierakstīt, jo krātuve ir atvienota."
-#: ../backends/telepathy/lib/tpf-persona.vala:499
-#: ../backends/telepathy/lib/tpf-persona.vala:520
-#: ../backends/telepathy/lib/tpf-persona.vala:572
-#: ../backends/telepathy/lib/tpf-persona.vala:586
+#: ../backends/telepathy/lib/tpf-persona.vala:511
+#: ../backends/telepathy/lib/tpf-persona.vala:532
+#: ../backends/telepathy/lib/tpf-persona.vala:584
+#: ../backends/telepathy/lib/tpf-persona.vala:598
#, c-format
msgid "Failed to change group membership: %s"
msgstr "Neizdevās izmainīt grupas piederību — %s"
#. Translators: "account" refers to an instant messaging
#. * account.
-#: ../backends/telepathy/lib/tpf-persona.vala:502
-#: ../backends/telepathy/lib/tpf-persona.vala:575
+#: ../backends/telepathy/lib/tpf-persona.vala:514
+#: ../backends/telepathy/lib/tpf-persona.vala:587
msgid "Account is offline."
msgstr "Konts ir bezsaistē."
#. Translators: the first parameter is the unknown key that
#. * was received with the details params, and the second
#. * identifies the persona store.
-#: ../backends/tracker/lib/trf-persona-store.vala:742
+#: ../backends/tracker/lib/trf-persona-store.vala:743
#, c-format
msgid "Unrecognized parameter '%s' passed to persona store '%s'."
msgstr "Neatpazīts parametrs “%s” nodots personas krātuvei “%s”."
@@ -407,19 +474,19 @@ msgstr "Segvārds nav rakstāms šim kontaktam."
#. Translators: the first parameter is a folder path and the second
#. * is an error message.
-#: ../folks/backend-store.vala:609
+#: ../folks/backend-store.vala:651
#, c-format
msgid "Error listing contents of folder '%s': %s"
msgstr "Kļūda, uzskaitot mapes “%s” saturu — %s"
#. Translators: the parameter is a filename.
-#: ../folks/backend-store.vala:739
+#: ../folks/backend-store.vala:786
#, c-format
msgid "File or directory '%s' does not exist."
msgstr "Datne vai direktorija “%s” neeksistē."
#. Translators: the parameter is a filename.
-#: ../folks/backend-store.vala:745
+#: ../folks/backend-store.vala:792
#, c-format
msgid "Failed to get content type for '%s'."
msgstr "Neizdevās iegūt satura tipu “%s”·"
@@ -441,31 +508,31 @@ msgstr "TZ adresi “%s” neizdevās atpazīt."
#. Translators: the first parameter is a persona store identifier
#. * and the second is an error message.
-#: ../folks/individual-aggregator.vala:921
+#: ../folks/individual-aggregator.vala:1040
#, c-format
msgid "Error preparing persona store '%s': %s"
msgstr "Kļūda, sagatavojot personas krātuvi “%s” — %s"
#. Translators: the parameter is a property name.
-#: ../folks/individual-aggregator.vala:1142
-#: ../folks/individual-aggregator.vala:1368
+#: ../folks/individual-aggregator.vala:1269
+#: ../folks/individual-aggregator.vala:1536
#, c-format
msgid "Unknown property '%s' in linkable property list."
msgstr "Nezināma īpašība “%s” saistīto īpašību sarakstā."
#. Translators: the first parameter is a store identifier
#. * and the second parameter is an error message.
-#: ../folks/individual-aggregator.vala:1830
+#: ../folks/individual-aggregator.vala:2022
#, c-format
msgid "Failed to add contact for persona store ID '%s': %s"
msgstr "Neizdevās pievienot kontaktu personas krātuves ID “%s” — %s"
-#: ../folks/individual-aggregator.vala:1931
+#: ../folks/individual-aggregator.vala:2119
msgid "Can’t link personas with no primary store."
msgstr "Nevar savienot personas, kurām nav primārās krātuves."
-#: ../folks/individual-aggregator.vala:1932
-#: ../folks/individual-aggregator.vala:2276
+#: ../folks/individual-aggregator.vala:2120
+#: ../folks/individual-aggregator.vala:2451
#, c-format
msgid ""
"Persona store ‘%s:%s’ is configured as primary, but could not be found or "
@@ -474,8 +541,8 @@ msgstr ""
"Personu krātuve “%s:%s” ir konfigurēta kā primārā, bet to neizdevās atrast "
"vai ielādēt."
-#: ../folks/individual-aggregator.vala:1933
-#: ../folks/individual-aggregator.vala:2277
+#: ../folks/individual-aggregator.vala:2121
+#: ../folks/individual-aggregator.vala:2452
#, c-format
msgid ""
"Check the relevant service is running, or change the default store in that "
@@ -484,26 +551,76 @@ msgstr ""
"Pārbaudiet, vai atbilstošais serviss strādā vai nomainiet noklusējuma "
"krātuvi tajā servisā, vai izmanto “%s” GSettings atslēgu."
-#: ../folks/individual-aggregator.vala:1965
+#: ../folks/individual-aggregator.vala:2153
msgid "Anti-links can't be removed between personas being linked."
msgstr "Anti-saites nevar izņemt starp savienotajām personām."
-#: ../folks/individual-aggregator.vala:2275
+#: ../folks/individual-aggregator.vala:2450
msgid "Can’t add personas with no primary store."
msgstr "Nevar pievienot personas, kurām nav primārās krātuves."
-#: ../folks/individual-aggregator.vala:2286
+#: ../folks/individual-aggregator.vala:2461
#, c-format
msgid "Can't write to requested property (“%s”) of the writeable store."
msgstr "Nevar ierakstīt pieprasīto īpašību (“%s”) no rakstāmas krātuves."
-#: ../folks/individual.vala:217 ../folks/individual.vala:370
-#: ../folks/individual.vala:479 ../folks/individual.vala:730
-#: ../folks/individual.vala:808
+#: ../folks/individual.vala:216 ../folks/individual.vala:402
+#: ../folks/individual.vala:511 ../folks/individual.vala:762
+#: ../folks/individual.vala:840
#, c-format
msgid "Failed to change property ‘%s’: No suitable personas were found."
msgstr "Neizdevās mainīt īpašību “%s” — netika atrasta piemērotas personas."
+#. Translators: This is the default name for an Individual
+#. * when displayed in the UI if no personal details are available
+#. * for them.
+#: ../folks/individual.vala:1951
+msgid "Unnamed Person"
+msgstr "Nenosaukta persona"
+
+#. FIXME: Ideally we’d use a format string translated to the locale of the
+#. * persona whose name is being formatted, but no backend provides
+#. * information about personas’ locales, so we have to settle for the
+#. * current user’s locale.
+#. *
+#. * We thought about using nl_langinfo(_NL_NAME_NAME_FMT) here, but
+#. * decided against it because:
+#. * 1. It’s not the best documented API in the world, and its stability
+#. * is in question.
+#. * 2. An attempt to improve the interface in glibc met with a wall of
+#. * complaints: https://sourceware.org/bugzilla/show_bug.cgi?id=14641.
+#. *
+#. * However, we do re-use the string format placeholders from
+#. * _NL_NAME_NAME_FMT (as documented here:
+#. * http://lh.2xlibre.net/values/name_fmt/) because there’s a chance glibc
+#. * might eventually grow a useful interface for this.
+#. *
+#. * It does mean we have to implement our own parser for the name_fmt
+#. * format though, since glibc doesn’t provide a formatting function.
+#. Translators: This is a format string used to convert structured names
+#. * to a single string. It should be translated to the predominant
+#. * semi-formal name format for your locale, using the placeholders
+#. * documented here: http://lh.2xlibre.net/values/name_fmt/. You may be
+#. * able to re-use the existing glibc format string for your locale on that
+#. * page if it’s suitable.
+#. *
+#. * More explicitly: the supported placeholders are %f, %F, %g, %G, %m, %M,
+#. * %t. The romanisation modifier (e.g. %Rf) is recognized but ignored.
+#. * %s, %S and %d are all replaced by the same thing (the ‘Honorific
+#. * Prefixes’ from vCard) so please avoid using more than one.
+#. *
+#. * For example, the format string ‘%g%t%m%t%f’ expands to ‘John Andrew
+#. * Lees’ when used for a persona with first name ‘John’, additional names
+#. * ‘Andrew’ and family names ‘Lees’.
+#. *
+#. * If you need additional placeholders with other information or
+#. * punctuation, please file a bug against libfolks:
+#. * https://bugzilla.gnome.org/enter_bug.cgi?product=folks
+#.
+#: ../folks/name-details.vala:268
+msgid "%g%t%m%t%f"
+msgstr "%g%t%m%t%f"
+
#: ../folks/org.freedesktop.folks.gschema.xml.in.h:1
msgid "Primary store ID"
msgstr "Primārās krātuves ID"
@@ -523,35 +640,35 @@ msgstr ""
msgid "%s, %s, %s, %s, %s, %s, %s"
msgstr "%s, %s, %s, %s, %s, %s, %s"
-#: ../folks/presence-details.vala:159
+#: ../folks/presence-details.vala:171
msgid "Unknown status"
msgstr "Nezināms statuss"
-#: ../folks/presence-details.vala:161
+#: ../folks/presence-details.vala:173
msgid "Offline"
msgstr "Bezsaistē"
-#: ../folks/presence-details.vala:165
+#: ../folks/presence-details.vala:177
msgid "Error"
msgstr "Kļūda"
-#: ../folks/presence-details.vala:167
+#: ../folks/presence-details.vala:179
msgid "Available"
msgstr "Pieejams"
-#: ../folks/presence-details.vala:169
+#: ../folks/presence-details.vala:181
msgid "Away"
msgstr "Projām"
-#: ../folks/presence-details.vala:171
+#: ../folks/presence-details.vala:183
msgid "Extended away"
msgstr "Ilglaicīgi projām"
-#: ../folks/presence-details.vala:173
+#: ../folks/presence-details.vala:185
msgid "Busy"
msgstr "Aizņemts"
-#: ../folks/presence-details.vala:175
+#: ../folks/presence-details.vala:187
msgid "Hidden"
msgstr "Slēpts"
@@ -653,54 +770,54 @@ msgstr "Avota aizmugures nosaukums (noklusējums — “pidgin”)"
msgid "Source filename (default: specific to source backend)"
msgstr "Avota datnes nosaukums (noklusējums — specifisks aizmugures avotam)"
-#: ../tools/import.vala:57
+#: ../tools/import.vala:58
msgid "— import meta-contact information to libfolks"
msgstr "— importēt meta-kontakta informāciju libfolks"
#. Translators: the parameter is an error message.
-#: ../tools/import.vala:67
+#: ../tools/import.vala:68
#, c-format
msgid "Couldn't parse command line options: %s"
msgstr "Neizdevās parsēt komandrindas opcijas — %s"
#. Translators: the parameter is an error message.
-#: ../tools/import.vala:108
+#: ../tools/import.vala:109
#, c-format
msgid "Couldn't load the backends: %s"
msgstr "Neizdevās ielādēt aizmugures — %s"
#. Translators: the parameter is a backend identifier.
-#: ../tools/import.vala:119
+#: ../tools/import.vala:120
#, c-format
msgid "Couldn't load the ‘%s’ backend."
msgstr "Neizdevās ielādēt “%s” aizmuguri."
#. Translators: the first parameter is a backend identifier and the
#. * second parameter is an error message.
-#: ../tools/import.vala:132
+#: ../tools/import.vala:133
#, c-format
msgid "Couldn't prepare the ‘%s’ backend: %s"
msgstr "Neizdevās sagatavot “%s” aizmuguri — %s"
#. Translators: the parameter is a backend identifier.
-#: ../tools/import.vala:145
+#: ../tools/import.vala:146
#, c-format
msgid "Couldn't load the ‘%s’ backend's persona store."
msgstr "Neizdevās ielādēt “%s” aizmugures personas krātuvi."
-#: ../tools/import.vala:166
+#: ../tools/import.vala:167
#, c-format
msgid "Couldn't prepare the ‘%s’ backend's persona store: %s"
msgstr "Neizdevās sagatavot “%s” aizmugures personas krātuvi — %s"
#. Translators: the parameter is an error message.
-#: ../tools/import.vala:184
+#: ../tools/import.vala:185
#, c-format
msgid "Error importing contacts: %s"
msgstr "Kļūda, importējot kontaktus — %s"
#. Translators: both parameters are identifiers for backends.
-#: ../tools/import.vala:198
+#: ../tools/import.vala:199
#, c-format
msgid ""
"Unrecognized source backend name ‘%s’. ‘%s’ is currently the only supported "
@@ -709,3 +826,9 @@ msgstr ""
"Neatpazīts avota aizmugures nosaukums “%s”. “%s” pašlaik ir vienīgā "
"atbalstītā avota aizmugure."
+#~ msgid ""
+#~ "Failed to determine whether we can set aliases on Telepathy account '%s': "
+#~ "%s"
+#~ msgstr ""
+#~ "Neizdevās noteikt, vai var iestatīt aizstājvārdus Telepathy kontā “%s” — "
+#~ "%s"
diff --git a/po/nb.po b/po/nb.po
index 9e3a26f2..6c8719d8 100644
--- a/po/nb.po
+++ b/po/nb.po
@@ -1,14 +1,14 @@
# Norwegian bokmål translation of folks.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
-# Kjartan Maraas <kmaraas@gnome.org>, 2011-2013.
+# Kjartan Maraas <kmaraas@gnome.org>, 2011-2014.
#
msgid ""
msgstr ""
-"Project-Id-Version: folks 0.7.x\n"
+"Project-Id-Version: folks 0.9.7\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2013-03-04 14:59+0100\n"
-"PO-Revision-Date: 2013-03-04 15:00+0100\n"
+"POT-Creation-Date: 2014-03-05 18:12+0100\n"
+"PO-Revision-Date: 2014-03-05 18:15+0100\n"
"Last-Translator: Kjartan Maraas <kmaraas@gnome.org>\n"
"Language-Team: Norwegian bokmål <i18n-nb@lister.ping.uio.no>\n"
"Language: \n"
@@ -17,6 +17,71 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n!=1);\n"
+#: ../backends/bluez/bluez-backend.vala:600
+msgid ""
+"No BlueZ 5 object manager running, so the BlueZ backend will be inactive. "
+"Either your BlueZ installation is too old (only version 5 is supported) or "
+"the service can’t be started."
+msgstr ""
+
+#: ../backends/bluez/bluez-backend.vala:613
+msgid ""
+"Error connecting to OBEX transfer daemon over D-Bus. Ensure BlueZ and obexd "
+"are installed."
+msgstr ""
+
+#. Translators: the parameter is an error message.
+#: ../backends/bluez/bluez-persona-store.vala:385
+#, c-format
+msgid "Error reading the transferred address book file: %s"
+msgstr "Feil ved lesing av overført adressebokfil: %s"
+
+#. Translators: the first parameter is the name of the
+#. * failed transfer, and the second is a Bluetooth device
+#. * alias.
+#. Translators: the first parameter is the name of the failed
+#. * transfer, and the second is a Bluetooth device alias.
+#: ../backends/bluez/bluez-persona-store.vala:667
+#: ../backends/bluez/bluez-persona-store.vala:689
+#, c-format
+msgid ""
+"Error during transfer of the address book ‘%s’ from Bluetooth device ‘%s’."
+msgstr "Feil under overføring av adressebok «%s» fra Bluetooth-enhet «%s»."
+
+#: ../backends/bluez/bluez-persona-store.vala:782
+#, c-format
+msgid ""
+"Permission to access the address book on Bluetooth device ‘%s’ was denied by "
+"the user."
+msgstr ""
+
+#. Translators: the first parameter is a Bluetooth device
+#. * alias, and the second is an error message.
+#: ../backends/bluez/bluez-persona-store.vala:789
+#, c-format
+msgid "An OBEX address book transfer from device ‘%s’ could not be started: %s"
+msgstr ""
+
+#. Translators: the first parameter is a Bluetooth device
+#. * alias, and the second is an error message.
+#: ../backends/bluez/bluez-persona-store.vala:829
+#, c-format
+msgid "The OBEX address book transfer from device ‘%s’ failed: %s"
+msgstr ""
+
+#. Translators: the first parameter is a Bluetooth device
+#. * alias, and the second is an error message.
+#: ../backends/bluez/bluez-persona-store.vala:846
+#, c-format
+msgid ""
+"Error during transfer of the address book from Bluetooth device ‘%s’: %s"
+msgstr ""
+
+#: ../backends/bluez/bluez-persona-store.vala:1064
+#, c-format
+msgid "Bluetooth device ‘%s’ disappeared during address book transfer."
+msgstr "Bluetooth-enhet «%s» forsvant under overføring av adressebok."
+
#. The timeout after which we consider a property change to have failed if we
#. * haven't received a property change notification for it.
#. seconds
@@ -31,68 +96,68 @@ msgstr "Stjernet i Android"
#. Translators: the first parameter is an address book
#. * URI and the second is a persona UID.
-#: ../backends/eds/lib/edsf-persona-store.vala:671
+#: ../backends/eds/lib/edsf-persona-store.vala:673
#, c-format
msgid "Address book ‘%s’ is offline, so contact ‘%s’ cannot be removed."
msgstr "Adressebok «%s» er frakoblet så kontakt «%s» kan ikke fjernes."
#. Translators: the first parameter is an address book
#. * URI and the second is an error message.
-#: ../backends/eds/lib/edsf-persona-store.vala:677
+#: ../backends/eds/lib/edsf-persona-store.vala:679
#, c-format
msgid "Permission denied to remove contact ‘%s’: %s"
msgstr "Tilgang til å fjerne kontakt «%s» nektet: %s"
#. Translators: the parameter is an error message.
-#: ../backends/eds/lib/edsf-persona-store.vala:682
+#: ../backends/eds/lib/edsf-persona-store.vala:684
#, c-format
msgid "Removing contacts isn't supported by this persona store: %s"
msgstr "Fjerning av kontakter støttes ikke av dette persona-lageret: %s"
-#: ../backends/eds/lib/edsf-persona-store.vala:711
+#: ../backends/eds/lib/edsf-persona-store.vala:713
#, c-format
msgid "Can't remove contact ‘%s’: %s"
msgstr "Kan ikke fjerne kontakt «%s»: %s"
#. Translators: the parameter is an address book
#. * URI.
-#: ../backends/eds/lib/edsf-persona-store.vala:801
-#: ../backends/eds/lib/edsf-persona-store.vala:992
+#: ../backends/eds/lib/edsf-persona-store.vala:802
+#: ../backends/eds/lib/edsf-persona-store.vala:993
#, c-format
msgid "Address book ‘%s’ is offline."
msgstr "Adressebok «%s» er frakoblet."
#. Translators: the first parameter is an address
#. * book URI and the second is an error message.
-#: ../backends/eds/lib/edsf-persona-store.vala:806
-#: ../backends/eds/lib/edsf-persona-store.vala:997
+#: ../backends/eds/lib/edsf-persona-store.vala:807
+#: ../backends/eds/lib/edsf-persona-store.vala:998
#, c-format
msgid "Permission denied to open address book ‘%s’: %s"
msgstr "Tilgang til å åpne adressebok «%s» nektet: %s"
#. Translators: the first parameter is an address book URI
#. * and the second is an error message.
-#: ../backends/eds/lib/edsf-persona-store.vala:839
+#: ../backends/eds/lib/edsf-persona-store.vala:840
#, c-format
msgid "Couldn't open address book ‘%s’: %s"
msgstr "Kunne ikke åpne adressebok «%s»: %s"
#. Translators: the parameteter is an error message.
-#: ../backends/eds/lib/edsf-persona-store.vala:905
-#: ../backends/eds/lib/edsf-persona-store.vala:935
+#: ../backends/eds/lib/edsf-persona-store.vala:906
+#: ../backends/eds/lib/edsf-persona-store.vala:936
#, c-format
msgid "Couldn't get address book capabilities: %s"
msgstr "Fant ikke evner for adressebok: %s"
#. Translators: the parameter is an address book URI.
-#: ../backends/eds/lib/edsf-persona-store.vala:951
+#: ../backends/eds/lib/edsf-persona-store.vala:952
#, c-format
msgid "Couldn't get view for address book ‘%s’."
msgstr "Fant ikke visning for adressebok «%s»."
#. Translators: the first parameter is an address book URI
#. * and the second is an error message.
-#: ../backends/eds/lib/edsf-persona-store.vala:1030
+#: ../backends/eds/lib/edsf-persona-store.vala:1031
#, c-format
msgid "Couldn't get view for address book ‘%s’: %s"
msgstr "Fant ikke visning for adressebokk «%s»: %s"
@@ -100,119 +165,119 @@ msgstr "Fant ikke visning for adressebokk «%s»: %s"
#. Translators: the parameter is the name of a property on a
#. * contact, formatted in the normal GObject style (e.g.
#. * lowercase with hyphens to separate words).
-#: ../backends/eds/lib/edsf-persona-store.vala:1390
+#: ../backends/eds/lib/edsf-persona-store.vala:1303
#, c-format
msgid "Changing the ‘%s’ property failed due to reaching the timeout."
msgstr "Endring av egenskap «%s» feilet på grunn av tidsavbrudd."
-#: ../backends/eds/lib/edsf-persona-store.vala:1428
+#: ../backends/eds/lib/edsf-persona-store.vala:1337
#: ../folks/avatar-details.vala:63
msgid "Avatar is not writeable on this contact."
msgstr "Avatar er ikke skrivbar på denne kontakten."
-#: ../backends/eds/lib/edsf-persona-store.vala:1449
+#: ../backends/eds/lib/edsf-persona-store.vala:1358
#: ../folks/web-service-details.vala:123
msgid "Web service addresses are not writeable on this contact."
msgstr "Webservice adresser er ikke skrivbare på denne kontakten."
-#: ../backends/eds/lib/edsf-persona-store.vala:1485
+#: ../backends/eds/lib/edsf-persona-store.vala:1394
#: ../folks/url-details.vala:152
msgid "URLs are not writeable on this contact."
msgstr "URLer er ikke skrivbare på denne kontakten."
-#: ../backends/eds/lib/edsf-persona-store.vala:1566
+#: ../backends/eds/lib/edsf-persona-store.vala:1475
#: ../folks/local-id-details.vala:64
msgid "Local IDs are not writeable on this contact."
msgstr "Lokale IDer er ikke skrivbare på denne kontakten."
-#: ../backends/eds/lib/edsf-persona-store.vala:1595
+#: ../backends/eds/lib/edsf-persona-store.vala:1504
msgid "The contact cannot be marked as favourite."
msgstr "Kontakten kan ikke merkes som favoritt."
#. Translators: the parameter is an error message.
-#: ../backends/eds/lib/edsf-persona-store.vala:1667
+#: ../backends/eds/lib/edsf-persona-store.vala:1576
#, c-format
msgid "Can't update avatar: %s"
msgstr "Kan ikke oppdatere avatar: %s"
-#: ../backends/eds/lib/edsf-persona-store.vala:1678
+#: ../backends/eds/lib/edsf-persona-store.vala:1587
#: ../folks/email-details.vala:120
msgid "E-mail addresses are not writeable on this contact."
msgstr "E-postadresser er ikke skrivbare på denne kontakten."
-#: ../backends/eds/lib/edsf-persona-store.vala:1696
-#: ../folks/phone-details.vala:224
+#: ../backends/eds/lib/edsf-persona-store.vala:1605
+#: ../folks/phone-details.vala:255
msgid "Phone numbers are not writeable on this contact."
msgstr "Telefonnummer er ikke skrivbare på denne kontakten."
-#: ../backends/eds/lib/edsf-persona-store.vala:1714
+#: ../backends/eds/lib/edsf-persona-store.vala:1623
#: ../folks/postal-address-details.vala:361
msgid "Postal addresses are not writeable on this contact."
msgstr "Postadresser er ikke skrivbare på denne kontakten."
-#: ../backends/eds/lib/edsf-persona-store.vala:1785
-#: ../folks/name-details.vala:283
+#: ../backends/eds/lib/edsf-persona-store.vala:1694
+#: ../folks/name-details.vala:454
msgid "Full name is not writeable on this contact."
msgstr "Fullt navn er ikke skrivbart på denne kontakten."
-#: ../backends/eds/lib/edsf-persona-store.vala:1807
-#: ../folks/name-details.vala:321
+#: ../backends/eds/lib/edsf-persona-store.vala:1716
+#: ../folks/name-details.vala:492
msgid "Nickname is not writeable on this contact."
msgstr "Kallenavn er ikke skrivbart på denne kontakten."
-#: ../backends/eds/lib/edsf-persona-store.vala:1829
+#: ../backends/eds/lib/edsf-persona-store.vala:1738
#: ../folks/note-details.vala:138
msgid "Notes are not writeable on this contact."
msgstr "Notater er ikke skrivbare på denne kontakten."
-#: ../backends/eds/lib/edsf-persona-store.vala:1861
+#: ../backends/eds/lib/edsf-persona-store.vala:1770
#: ../folks/birthday-details.vala:62
msgid "Birthday is not writeable on this contact."
msgstr "Fødselsdag er ikke skrivbar på denne kontakten."
-#: ../backends/eds/lib/edsf-persona-store.vala:1905
+#: ../backends/eds/lib/edsf-persona-store.vala:1814
#: ../folks/role-details.vala:279
msgid "Roles are not writeable on this contact."
msgstr "Roller er ikke skrivbare på denne kontakten."
-#: ../backends/eds/lib/edsf-persona-store.vala:2006
-#: ../folks/name-details.vala:246
+#: ../backends/eds/lib/edsf-persona-store.vala:1915
+#: ../folks/name-details.vala:417
msgid "Structured name is not writeable on this contact."
msgstr "Strukturert navn er ikke skrivbart på denne kontakten."
-#: ../backends/eds/lib/edsf-persona-store.vala:2045
+#: ../backends/eds/lib/edsf-persona-store.vala:1954
#: ../folks/im-details.vala:136
msgid "IM addresses are not writeable on this contact."
msgstr "Lynmeldingsadresser er ikke skrivbare på denne kontakten."
-#: ../backends/eds/lib/edsf-persona-store.vala:2095
+#: ../backends/eds/lib/edsf-persona-store.vala:2004
#: ../folks/group-details.vala:174
msgid "Groups are not writeable on this contact."
msgstr "Grupper er ikke skrivbare på denne kontakten."
-#: ../backends/eds/lib/edsf-persona-store.vala:2110
+#: ../backends/eds/lib/edsf-persona-store.vala:2019
msgid "My Contacts is only available for Google Contacts"
msgstr "Mine kontakter er kun tilgjengelig for Google-kontakter"
-#: ../backends/eds/lib/edsf-persona-store.vala:2181
+#: ../backends/eds/lib/edsf-persona-store.vala:2090
#: ../folks/gender-details.vala:79
msgid "Gender is not writeable on this contact."
msgstr "Kjønn er ikke skrivbart på denne kontakten."
-#: ../backends/eds/lib/edsf-persona-store.vala:2219
+#: ../backends/eds/lib/edsf-persona-store.vala:2128
#: ../folks/anti-linkable.vala:81
msgid "Anti-links are not writeable on this contact."
msgstr "Anti-lenker er ikke skrivbare på denne kontakten."
-#: ../backends/eds/lib/edsf-persona-store.vala:2262
-#: ../folks/location-details.vala:129
+#: ../backends/eds/lib/edsf-persona-store.vala:2171
+#: ../folks/location-details.vala:135
msgid "Location is not writeable on this contact."
msgstr "Lokasjon er ikke skrivbar på denne kontakten."
#. Translators: the first parameter is a non-human-readable
#. * property name and the second parameter is an error
#. * message.
-#: ../backends/eds/lib/edsf-persona-store.vala:2439
+#: ../backends/eds/lib/edsf-persona-store.vala:2484
#, c-format
msgid "Property ‘%s’ is not writeable: %s"
msgstr "Egenskap «%s» er ikke skrivbar: %s"
@@ -220,42 +285,42 @@ msgstr "Egenskap «%s» er ikke skrivbar: %s"
#. Translators: the first parameter is a non-human-readable
#. * property name and the second parameter is an error
#. * message.
-#: ../backends/eds/lib/edsf-persona-store.vala:2448
+#: ../backends/eds/lib/edsf-persona-store.vala:2493
#, c-format
msgid "Invalid value for property ‘%s’: %s"
msgstr "Ugyldig verdi for egenskap «%s»: %s"
#. Translators: the first parameter is a non-human-readable
#. * property name and the second parameter is an error message.
-#: ../backends/eds/lib/edsf-persona-store.vala:2474
+#: ../backends/eds/lib/edsf-persona-store.vala:2519
#, c-format
msgid "Unknown error setting property ‘%s’: %s"
msgstr "Ukjent feil ved setting av egenskap «%s»: %s"
#. Translators: the first parameter is a filename, and
#. * the second is an error message.
-#: ../backends/key-file/kf-persona-store.vala:233
+#: ../backends/key-file/kf-persona-store.vala:234
#, c-format
msgid "The relationship key file '%s' could not be loaded: %s"
msgstr "Nøkkelfil «%s» for relasjon kunne ikke lastes: %s"
#. Translators: the first parameter is a path, and the
#. * second is an error message.
-#: ../backends/key-file/kf-persona-store.vala:255
+#: ../backends/key-file/kf-persona-store.vala:256
#, c-format
msgid "The relationship key file directory '%s' could not be created: %s"
msgstr "Katalog «%s» for katalog for relasjonsfil kunne ikke opprettes: %s"
#. Translators: the first parameter is a filename, and
#. * the second is an error message.
-#: ../backends/key-file/kf-persona-store.vala:279
+#: ../backends/key-file/kf-persona-store.vala:280
#, c-format
msgid "The relationship key file '%s' could not be created: %s"
msgstr "Nøkkelfil «%s» for relasjon kunne ikke opprettes: %s"
#. Translators: the first parameter is a filename, the second is
#. * an error message.
-#: ../backends/key-file/kf-persona-store.vala:470
+#: ../backends/key-file/kf-persona-store.vala:471
#, c-format
msgid "Could not write updated key file '%s': %s"
msgstr "Kunne ikke skrive oppdatert nøkkelfil «%s»: %s"
@@ -265,13 +330,13 @@ msgstr "Kunne ikke skrive oppdatert nøkkelfil «%s»: %s"
#. * an IM address (e.g. “foo@jabber.org”), the second is
#. * the name of a protocol (e.g. “jabber”) and the third is
#. * an error message.
-#: ../backends/key-file/kf-persona.vala:172
+#: ../backends/key-file/kf-persona.vala:174
#, c-format
msgid "Invalid IM address ‘%s’ for protocol ‘%s’: %s"
msgstr "Ugyldig lynmeldingsadresse «%s» for protokoll «%s»: %s"
#. Translators: the parameter is an error message.
-#: ../backends/key-file/kf-persona.vala:430
+#: ../backends/key-file/kf-persona.vala:432
#, c-format
msgid "Couldn't load data from key file: %s"
msgstr "Kunne ikke laste data fra nøkkelfil: %s"
@@ -296,27 +361,24 @@ msgstr "Ingen evner funnet for kontakter."
msgid "Error opening contacts view."
msgstr "Feil ved åpning av kontaktvisning."
-#. Translators: the first parameter is the display name for
-#. * the Telepathy account, and the second is an error
-#. * message.
-#: ../backends/telepathy/lib/tpf-persona-store.vala:814
-#, c-format
+#: ../backends/ofono/ofono-backend.vala:196
msgid ""
-"Failed to determine whether we can set aliases on Telepathy account '%s': %s"
+"No oFono object manager running, so the oFono backend will be inactive. "
+"Either oFono isn’t installed or the service can’t be started."
msgstr ""
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1278
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1248
msgid "Telepathy contacts representing the local user may not be removed."
msgstr ""
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1289
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1259
#, c-format
msgid "Failed to remove a persona from store: %s"
msgstr "Klarte ikke å fjerne en persona fra lageret: %s"
#. Translators: the first two parameters are store identifiers and
#. * the third is a contact identifier.
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1324
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1294
#, c-format
msgid ""
"Persona store (%s, %s) requires the following details:\n"
@@ -325,69 +387,69 @@ msgstr ""
"Personalager (%s, %s) krever følgende detaljer:\n"
" kontakt (oppgitt: «%s»)\n"
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1339
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1309
msgid "Cannot create a new Telepathy contact while offline."
msgstr "Kan ikke lage en ny Telepathy-kontakt i frakoblet modus."
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1357
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1327
#, c-format
msgid "Failed to add a persona from details: %s"
msgstr "Klarte ikke å legge til persona fra detaljer: %s"
#. Translators: "telepathy-logger" is the name of an application,
#. * and should not be translated.
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1377
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1347
msgid ""
"Failed to change favorite without a connection to the telepathy-logger "
"service."
msgstr ""
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1383
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1353
msgid ""
"Failed to change favorite status of Telepathy Persona because it has no "
"attached TpContact."
msgstr ""
#. Translators: the parameter is a contact identifier.
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1401
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1371
#, c-format
msgid "Failed to change favorite status for Telepathy contact ‘%s’."
msgstr ""
#. Translators: the parameter is an error message.
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1433
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1403
#, c-format
msgid "Failed to change contact's alias: %s"
msgstr "Klarte ikke å endre kontaktens alias: %s"
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1513
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1484
msgid "Extended information may only be set on the user's Telepathy contact."
msgstr ""
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1542
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1513
msgid ""
"Extended information cannot be written because the store is disconnected."
msgstr ""
-#: ../backends/telepathy/lib/tpf-persona.vala:499
-#: ../backends/telepathy/lib/tpf-persona.vala:520
-#: ../backends/telepathy/lib/tpf-persona.vala:572
-#: ../backends/telepathy/lib/tpf-persona.vala:586
+#: ../backends/telepathy/lib/tpf-persona.vala:511
+#: ../backends/telepathy/lib/tpf-persona.vala:532
+#: ../backends/telepathy/lib/tpf-persona.vala:584
+#: ../backends/telepathy/lib/tpf-persona.vala:598
#, c-format
msgid "Failed to change group membership: %s"
msgstr "Klarte ikke å endre gruppemedlemskap: %s"
#. Translators: "account" refers to an instant messaging
#. * account.
-#: ../backends/telepathy/lib/tpf-persona.vala:502
-#: ../backends/telepathy/lib/tpf-persona.vala:575
+#: ../backends/telepathy/lib/tpf-persona.vala:514
+#: ../backends/telepathy/lib/tpf-persona.vala:587
msgid "Account is offline."
msgstr "Kontoen er frakoblet."
#. Translators: the first parameter is the unknown key that
#. * was received with the details params, and the second
#. * identifies the persona store.
-#: ../backends/tracker/lib/trf-persona-store.vala:742
+#: ../backends/tracker/lib/trf-persona-store.vala:743
#, c-format
msgid "Unrecognized parameter '%s' passed to persona store '%s'."
msgstr ""
@@ -398,19 +460,19 @@ msgstr "Alias er ikke skrivbart på denne kontakten."
#. Translators: the first parameter is a folder path and the second
#. * is an error message.
-#: ../folks/backend-store.vala:609
+#: ../folks/backend-store.vala:651
#, c-format
msgid "Error listing contents of folder '%s': %s"
msgstr "Feil ved visning av innhold for mappe «%s»: %s"
#. Translators: the parameter is a filename.
-#: ../folks/backend-store.vala:739
+#: ../folks/backend-store.vala:786
#, c-format
msgid "File or directory '%s' does not exist."
msgstr "Fil eller katalog «%s» eksisterer ikke."
#. Translators: the parameter is a filename.
-#: ../folks/backend-store.vala:745
+#: ../folks/backend-store.vala:792
#, c-format
msgid "Failed to get content type for '%s'."
msgstr "Klarte ikke å finne innholdstype for «%s»."
@@ -432,65 +494,115 @@ msgstr "IM-adresse «%s» kunne ikke forstås."
#. Translators: the first parameter is a persona store identifier
#. * and the second is an error message.
-#: ../folks/individual-aggregator.vala:921
+#: ../folks/individual-aggregator.vala:1040
#, c-format
msgid "Error preparing persona store '%s': %s"
msgstr "Feil ved klargjøring av persona-lager «%s»: %s"
#. Translators: the parameter is a property name.
-#: ../folks/individual-aggregator.vala:1142
-#: ../folks/individual-aggregator.vala:1368
+#: ../folks/individual-aggregator.vala:1269
+#: ../folks/individual-aggregator.vala:1536
#, c-format
msgid "Unknown property '%s' in linkable property list."
msgstr "Ukjent egenskap «%s» i lenkbar egenskapsliste."
#. Translators: the first parameter is a store identifier
#. * and the second parameter is an error message.
-#: ../folks/individual-aggregator.vala:1830
+#: ../folks/individual-aggregator.vala:2022
#, c-format
msgid "Failed to add contact for persona store ID '%s': %s"
msgstr ""
-#: ../folks/individual-aggregator.vala:1931
+#: ../folks/individual-aggregator.vala:2119
msgid "Can’t link personas with no primary store."
msgstr "Kan ikke lenke personas uten primærlager."
-#: ../folks/individual-aggregator.vala:1932
-#: ../folks/individual-aggregator.vala:2276
+#: ../folks/individual-aggregator.vala:2120
+#: ../folks/individual-aggregator.vala:2451
#, c-format
msgid ""
"Persona store ‘%s:%s’ is configured as primary, but could not be found or "
"failed to load."
msgstr ""
-#: ../folks/individual-aggregator.vala:1933
-#: ../folks/individual-aggregator.vala:2277
+#: ../folks/individual-aggregator.vala:2121
+#: ../folks/individual-aggregator.vala:2452
#, c-format
msgid ""
"Check the relevant service is running, or change the default store in that "
"service or using the “%s” GSettings key."
msgstr ""
-#: ../folks/individual-aggregator.vala:1965
+#: ../folks/individual-aggregator.vala:2153
msgid "Anti-links can't be removed between personas being linked."
msgstr ""
-#: ../folks/individual-aggregator.vala:2275
+#: ../folks/individual-aggregator.vala:2450
msgid "Can’t add personas with no primary store."
msgstr "Kan ikke legge til personas uten primærlager."
-#: ../folks/individual-aggregator.vala:2286
+#: ../folks/individual-aggregator.vala:2461
#, c-format
msgid "Can't write to requested property (“%s”) of the writeable store."
msgstr ""
-#: ../folks/individual.vala:217 ../folks/individual.vala:370
-#: ../folks/individual.vala:479 ../folks/individual.vala:730
-#: ../folks/individual.vala:808
+#: ../folks/individual.vala:216 ../folks/individual.vala:402
+#: ../folks/individual.vala:511 ../folks/individual.vala:762
+#: ../folks/individual.vala:840
#, c-format
msgid "Failed to change property ‘%s’: No suitable personas were found."
msgstr ""
+#. Translators: This is the default name for an Individual
+#. * when displayed in the UI if no personal details are available
+#. * for them.
+#: ../folks/individual.vala:1951
+msgid "Unnamed Person"
+msgstr "Person uten navn"
+
+#. FIXME: Ideally we’d use a format string translated to the locale of the
+#. * persona whose name is being formatted, but no backend provides
+#. * information about personas’ locales, so we have to settle for the
+#. * current user’s locale.
+#. *
+#. * We thought about using nl_langinfo(_NL_NAME_NAME_FMT) here, but
+#. * decided against it because:
+#. * 1. It’s not the best documented API in the world, and its stability
+#. * is in question.
+#. * 2. An attempt to improve the interface in glibc met with a wall of
+#. * complaints: https://sourceware.org/bugzilla/show_bug.cgi?id=14641.
+#. *
+#. * However, we do re-use the string format placeholders from
+#. * _NL_NAME_NAME_FMT (as documented here:
+#. * http://lh.2xlibre.net/values/name_fmt/) because there’s a chance glibc
+#. * might eventually grow a useful interface for this.
+#. *
+#. * It does mean we have to implement our own parser for the name_fmt
+#. * format though, since glibc doesn’t provide a formatting function.
+#. Translators: This is a format string used to convert structured names
+#. * to a single string. It should be translated to the predominant
+#. * semi-formal name format for your locale, using the placeholders
+#. * documented here: http://lh.2xlibre.net/values/name_fmt/. You may be
+#. * able to re-use the existing glibc format string for your locale on that
+#. * page if it’s suitable.
+#. *
+#. * More explicitly: the supported placeholders are %f, %F, %g, %G, %m, %M,
+#. * %t. The romanisation modifier (e.g. %Rf) is recognized but ignored.
+#. * %s, %S and %d are all replaced by the same thing (the ‘Honorific
+#. * Prefixes’ from vCard) so please avoid using more than one.
+#. *
+#. * For example, the format string ‘%g%t%m%t%f’ expands to ‘John Andrew
+#. * Lees’ when used for a persona with first name ‘John’, additional names
+#. * ‘Andrew’ and family names ‘Lees’.
+#. *
+#. * If you need additional placeholders with other information or
+#. * punctuation, please file a bug against libfolks:
+#. * https://bugzilla.gnome.org/enter_bug.cgi?product=folks
+#.
+#: ../folks/name-details.vala:268
+msgid "%g%t%m%t%f"
+msgstr "%g%t%m%t%f"
+
#: ../folks/org.freedesktop.folks.gschema.xml.in.h:1
msgid "Primary store ID"
msgstr "ID for primærlager"
@@ -507,35 +619,35 @@ msgstr ""
msgid "%s, %s, %s, %s, %s, %s, %s"
msgstr "%s, %s, %s, %s, %s, %s, %s"
-#: ../folks/presence-details.vala:159
+#: ../folks/presence-details.vala:171
msgid "Unknown status"
msgstr "Ukjent status"
-#: ../folks/presence-details.vala:161
+#: ../folks/presence-details.vala:173
msgid "Offline"
msgstr "Frakoblet"
-#: ../folks/presence-details.vala:165
+#: ../folks/presence-details.vala:177
msgid "Error"
msgstr "Feil"
-#: ../folks/presence-details.vala:167
+#: ../folks/presence-details.vala:179
msgid "Available"
msgstr "Tilgjengelig"
-#: ../folks/presence-details.vala:169
+#: ../folks/presence-details.vala:181
msgid "Away"
msgstr "Borte"
-#: ../folks/presence-details.vala:171
+#: ../folks/presence-details.vala:183
msgid "Extended away"
msgstr "Utvidet borte"
-#: ../folks/presence-details.vala:173
+#: ../folks/presence-details.vala:185
msgid "Busy"
msgstr "Opptatt"
-#: ../folks/presence-details.vala:175
+#: ../folks/presence-details.vala:187
msgid "Hidden"
msgstr "Skjult"
@@ -628,60 +740,60 @@ msgstr ""
#: ../tools/import.vala:44
msgid "Source backend name (default: 'pidgin')"
-msgstr ""
+msgstr "Navn på motor for kilde (forvalgt: «pidgin»)"
#: ../tools/import.vala:47
msgid "Source filename (default: specific to source backend)"
-msgstr ""
+msgstr "Filnavn for kilde (forvalg: spesifikk for kildemotor)"
-#: ../tools/import.vala:57
+#: ../tools/import.vala:58
msgid "— import meta-contact information to libfolks"
msgstr "– importer metainformasjon for kontakt til libfolks"
#. Translators: the parameter is an error message.
-#: ../tools/import.vala:67
+#: ../tools/import.vala:68
#, c-format
msgid "Couldn't parse command line options: %s"
msgstr "Kunne ikke lese kommandolinjeflagg: %s"
#. Translators: the parameter is an error message.
-#: ../tools/import.vala:108
+#: ../tools/import.vala:109
#, c-format
msgid "Couldn't load the backends: %s"
msgstr "Kunne ikke laste motorer: %s"
#. Translators: the parameter is a backend identifier.
-#: ../tools/import.vala:119
+#: ../tools/import.vala:120
#, c-format
msgid "Couldn't load the ‘%s’ backend."
msgstr "Kunne ikke laste motor «%s»"
#. Translators: the first parameter is a backend identifier and the
#. * second parameter is an error message.
-#: ../tools/import.vala:132
+#: ../tools/import.vala:133
#, c-format
msgid "Couldn't prepare the ‘%s’ backend: %s"
msgstr "Kunne ikke klargjøre motor «%s»: %s"
#. Translators: the parameter is a backend identifier.
-#: ../tools/import.vala:145
+#: ../tools/import.vala:146
#, c-format
msgid "Couldn't load the ‘%s’ backend's persona store."
msgstr "Kunne ikke laste personalager for motor «%s»."
-#: ../tools/import.vala:166
+#: ../tools/import.vala:167
#, c-format
msgid "Couldn't prepare the ‘%s’ backend's persona store: %s"
msgstr "Kunne ikke klargjøre personalager for motor «%s»: %s"
#. Translators: the parameter is an error message.
-#: ../tools/import.vala:184
+#: ../tools/import.vala:185
#, c-format
msgid "Error importing contacts: %s"
msgstr "Feil ved import av kontakter: %s"
#. Translators: both parameters are identifiers for backends.
-#: ../tools/import.vala:198
+#: ../tools/import.vala:199
#, c-format
msgid ""
"Unrecognized source backend name ‘%s’. ‘%s’ is currently the only supported "
diff --git a/po/pt.po b/po/pt.po
index 4586c24c..17d358ea 100644
--- a/po/pt.po
+++ b/po/pt.po
@@ -1,14 +1,15 @@
# folks' Portuguese translation.
-# Copyright © 2012, 2013 folks
+# Copyright © 2012, 2013, 2014 folks
# This file is distributed under the same license as the folks package.
-# Duarte Loreto <happyguy_pt@hotmail.com>, 2012, 2013.
+# Duarte Loreto <happyguy_pt@hotmail.com>, 2012, 2013, 2014.
#
msgid ""
msgstr ""
-"Project-Id-Version: 3.8\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2013-03-15 01:26+0000\n"
-"PO-Revision-Date: 2013-03-15 01:30+0100\n"
+"Project-Id-Version: 3.12\n"
+"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?"
+"product=folks&keywords=I18N+L10N&component=general\n"
+"POT-Creation-Date: 2014-03-18 05:54+0000\n"
+"PO-Revision-Date: 2014-03-18 10:20+0100\n"
"Last-Translator: Duarte Loreto <happyguy_pt@hotmail.com>\n"
"Language-Team: Portuguese <gnome_pt@yahoogroups.com>\n"
"Language: pt\n"
@@ -17,6 +18,81 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+#: ../backends/bluez/bluez-backend.vala:600
+msgid ""
+"No BlueZ 5 object manager running, so the BlueZ backend will be inactive. "
+"Either your BlueZ installation is too old (only version 5 is supported) or "
+"the service can’t be started."
+msgstr ""
+"Nenhum gestor de objetos BlueZ 5 em execução, pelo que o motor BlueZ irá "
+"estar inativo. Ou a sua instalação BlueZ é demasiado antiga (apenas é "
+"suportada a versão 5) ou não está a ser possível iniciar o serviço."
+
+#: ../backends/bluez/bluez-backend.vala:613
+msgid ""
+"Error connecting to OBEX transfer daemon over D-Bus. Ensure BlueZ and obexd "
+"are installed."
+msgstr ""
+"Erro ao se ligar ao daemon de transferência OBEX através do D-Bus. "
+"Certifique-se de que o BlueZ e o obexd estão instalados."
+
+#. Translators: the parameter is an error message.
+#: ../backends/bluez/bluez-persona-store.vala:385
+#, c-format
+msgid "Error reading the transferred address book file: %s"
+msgstr "Erro ao ler o ficheiro de livro de endereços transferido: %s"
+
+#. Translators: the first parameter is the name of the
+#. * failed transfer, and the second is a Bluetooth device
+#. * alias.
+#. Translators: the first parameter is the name of the failed
+#. * transfer, and the second is a Bluetooth device alias.
+#: ../backends/bluez/bluez-persona-store.vala:667
+#: ../backends/bluez/bluez-persona-store.vala:689
+#, c-format
+msgid ""
+"Error during transfer of the address book ‘%s’ from Bluetooth device ‘%s’."
+msgstr ""
+"Erro durante a transferência do livro de endereços ‘%s’ do dispositivo Bluetooth ‘%s’."
+
+#: ../backends/bluez/bluez-persona-store.vala:782
+#, c-format
+msgid ""
+"Permission to access the address book on Bluetooth device ‘%s’ was denied by "
+"the user."
+msgstr ""
+"Permissão negada pelo utilizador para aceder ao livro de endereços no dispositivo "
+"Bluetooth ‘%s’."
+
+#. Translators: the first parameter is a Bluetooth device
+#. * alias, and the second is an error message.
+#: ../backends/bluez/bluez-persona-store.vala:789
+#, c-format
+msgid "An OBEX address book transfer from device ‘%s’ could not be started: %s"
+msgstr "Um livro de endereços OBEX transferido do dispositivo ‘%s’ não pode ser iniciado: %s"
+
+#. Translators: the first parameter is a Bluetooth device
+#. * alias, and the second is an error message.
+#: ../backends/bluez/bluez-persona-store.vala:829
+#, c-format
+msgid "The OBEX address book transfer from device ‘%s’ failed: %s"
+msgstr "O livro de endereços OBEX transferido do dispositivo ‘%s’ falhou: %s"
+
+#. Translators: the first parameter is a Bluetooth device
+#. * alias, and the second is an error message.
+#: ../backends/bluez/bluez-persona-store.vala:846
+#, c-format
+msgid ""
+"Error during transfer of the address book from Bluetooth device ‘%s’: %s"
+msgstr ""
+"Erro durante a transferência do livro de endereços do dispositivo Bluetooth "
+"‘%s’: %s"
+
+#: ../backends/bluez/bluez-persona-store.vala:1064
+#, c-format
+msgid "Bluetooth device ‘%s’ disappeared during address book transfer."
+msgstr "Dispositivo Bluetooth ‘%s’ desapareceu durante a transferência do livro de endereços."
+
#. The timeout after which we consider a property change to have failed if we
#. * haven't received a property change notification for it.
#. seconds
@@ -31,7 +107,7 @@ msgstr "Starred in Android"
#. Translators: the first parameter is an address book
#. * URI and the second is a persona UID.
-#: ../backends/eds/lib/edsf-persona-store.vala:671
+#: ../backends/eds/lib/edsf-persona-store.vala:673
#, c-format
msgid "Address book ‘%s’ is offline, so contact ‘%s’ cannot be removed."
msgstr ""
@@ -40,62 +116,62 @@ msgstr ""
#. Translators: the first parameter is an address book
#. * URI and the second is an error message.
-#: ../backends/eds/lib/edsf-persona-store.vala:677
+#: ../backends/eds/lib/edsf-persona-store.vala:679
#, c-format
msgid "Permission denied to remove contact ‘%s’: %s"
msgstr "Autorização negada para remover o contacto ‘%s’: %s"
#. Translators: the parameter is an error message.
-#: ../backends/eds/lib/edsf-persona-store.vala:682
+#: ../backends/eds/lib/edsf-persona-store.vala:684
#, c-format
msgid "Removing contacts isn't supported by this persona store: %s"
msgstr ""
"Remover contactos não é suportado por este armazenamento de personas: %s"
-#: ../backends/eds/lib/edsf-persona-store.vala:711
+#: ../backends/eds/lib/edsf-persona-store.vala:713
#, c-format
msgid "Can't remove contact ‘%s’: %s"
msgstr "Incapaz de remover o contacto ‘%s’: %s"
#. Translators: the parameter is an address book
#. * URI.
-#: ../backends/eds/lib/edsf-persona-store.vala:801
-#: ../backends/eds/lib/edsf-persona-store.vala:992
+#: ../backends/eds/lib/edsf-persona-store.vala:802
+#: ../backends/eds/lib/edsf-persona-store.vala:993
#, c-format
msgid "Address book ‘%s’ is offline."
msgstr "O livro de endereços ‘%s’ está desligado."
#. Translators: the first parameter is an address
#. * book URI and the second is an error message.
-#: ../backends/eds/lib/edsf-persona-store.vala:806
-#: ../backends/eds/lib/edsf-persona-store.vala:997
+#: ../backends/eds/lib/edsf-persona-store.vala:807
+#: ../backends/eds/lib/edsf-persona-store.vala:998
#, c-format
msgid "Permission denied to open address book ‘%s’: %s"
msgstr "Autorização negada para abrir o calendário ‘%s’: %s"
#. Translators: the first parameter is an address book URI
#. * and the second is an error message.
-#: ../backends/eds/lib/edsf-persona-store.vala:839
+#: ../backends/eds/lib/edsf-persona-store.vala:840
#, c-format
msgid "Couldn't open address book ‘%s’: %s"
msgstr "Incapaz de abrir o livro de endereços ‘%s’: %s"
#. Translators: the parameteter is an error message.
-#: ../backends/eds/lib/edsf-persona-store.vala:905
-#: ../backends/eds/lib/edsf-persona-store.vala:935
+#: ../backends/eds/lib/edsf-persona-store.vala:906
+#: ../backends/eds/lib/edsf-persona-store.vala:936
#, c-format
msgid "Couldn't get address book capabilities: %s"
msgstr "Incapaz de obter as capacidades do livro de endereços: %s"
#. Translators: the parameter is an address book URI.
-#: ../backends/eds/lib/edsf-persona-store.vala:951
+#: ../backends/eds/lib/edsf-persona-store.vala:952
#, c-format
msgid "Couldn't get view for address book ‘%s’."
msgstr "Incapaz de obter a vista do livro de endereços ‘%s’."
#. Translators: the first parameter is an address book URI
#. * and the second is an error message.
-#: ../backends/eds/lib/edsf-persona-store.vala:1030
+#: ../backends/eds/lib/edsf-persona-store.vala:1031
#, c-format
msgid "Couldn't get view for address book ‘%s’: %s"
msgstr "Incapaz de obter a vista do livro de endereços ‘%s’: %s"
@@ -103,120 +179,120 @@ msgstr "Incapaz de obter a vista do livro de endereços ‘%s’: %s"
#. Translators: the parameter is the name of a property on a
#. * contact, formatted in the normal GObject style (e.g.
#. * lowercase with hyphens to separate words).
-#: ../backends/eds/lib/edsf-persona-store.vala:1390
+#: ../backends/eds/lib/edsf-persona-store.vala:1303
#, c-format
msgid "Changing the ‘%s’ property failed due to reaching the timeout."
msgstr ""
"Falha ao alterar a propriedade ‘%s’ por se ter excedido o tempo de espera."
-#: ../backends/eds/lib/edsf-persona-store.vala:1428
+#: ../backends/eds/lib/edsf-persona-store.vala:1337
#: ../folks/avatar-details.vala:63
msgid "Avatar is not writeable on this contact."
msgstr "Não é possível escrever o avatar neste contacto."
-#: ../backends/eds/lib/edsf-persona-store.vala:1449
+#: ../backends/eds/lib/edsf-persona-store.vala:1358
#: ../folks/web-service-details.vala:123
msgid "Web service addresses are not writeable on this contact."
msgstr "Não é possível escrever os endereços de serviço web neste contacto."
-#: ../backends/eds/lib/edsf-persona-store.vala:1485
+#: ../backends/eds/lib/edsf-persona-store.vala:1394
#: ../folks/url-details.vala:152
msgid "URLs are not writeable on this contact."
msgstr "Não é possível escrever os URLs neste contacto."
-#: ../backends/eds/lib/edsf-persona-store.vala:1566
+#: ../backends/eds/lib/edsf-persona-store.vala:1475
#: ../folks/local-id-details.vala:64
msgid "Local IDs are not writeable on this contact."
msgstr "Não é possível escrever os IDs locais neste contacto."
-#: ../backends/eds/lib/edsf-persona-store.vala:1595
+#: ../backends/eds/lib/edsf-persona-store.vala:1504
msgid "The contact cannot be marked as favourite."
msgstr "Este contacto não pode ser marcado como favorito."
#. Translators: the parameter is an error message.
-#: ../backends/eds/lib/edsf-persona-store.vala:1667
+#: ../backends/eds/lib/edsf-persona-store.vala:1576
#, c-format
msgid "Can't update avatar: %s"
msgstr "Incapaz de atualizar avatar: %s"
-#: ../backends/eds/lib/edsf-persona-store.vala:1678
+#: ../backends/eds/lib/edsf-persona-store.vala:1587
#: ../folks/email-details.vala:120
msgid "E-mail addresses are not writeable on this contact."
msgstr "Não é possível escrever os endereços de email neste contacto."
-#: ../backends/eds/lib/edsf-persona-store.vala:1696
-#: ../folks/phone-details.vala:224
+#: ../backends/eds/lib/edsf-persona-store.vala:1605
+#: ../folks/phone-details.vala:255
msgid "Phone numbers are not writeable on this contact."
msgstr "Não é possível escrever os números de telefone neste contacto."
-#: ../backends/eds/lib/edsf-persona-store.vala:1714
+#: ../backends/eds/lib/edsf-persona-store.vala:1623
#: ../folks/postal-address-details.vala:361
msgid "Postal addresses are not writeable on this contact."
msgstr "Não é possível escrever os endereços postais neste contacto."
-#: ../backends/eds/lib/edsf-persona-store.vala:1785
-#: ../folks/name-details.vala:283
+#: ../backends/eds/lib/edsf-persona-store.vala:1694
+#: ../folks/name-details.vala:454
msgid "Full name is not writeable on this contact."
msgstr "Não é possível escrever o nome completo neste contacto."
-#: ../backends/eds/lib/edsf-persona-store.vala:1807
-#: ../folks/name-details.vala:321
+#: ../backends/eds/lib/edsf-persona-store.vala:1716
+#: ../folks/name-details.vala:492
msgid "Nickname is not writeable on this contact."
msgstr "Não é possível escrever a alcunha neste contacto."
-#: ../backends/eds/lib/edsf-persona-store.vala:1829
+#: ../backends/eds/lib/edsf-persona-store.vala:1738
#: ../folks/note-details.vala:138
msgid "Notes are not writeable on this contact."
msgstr "Não é possível escrever notas sobre neste contacto."
-#: ../backends/eds/lib/edsf-persona-store.vala:1861
+#: ../backends/eds/lib/edsf-persona-store.vala:1770
#: ../folks/birthday-details.vala:62
msgid "Birthday is not writeable on this contact."
msgstr "Não é possível escrever o aniversário deste contacto."
-#: ../backends/eds/lib/edsf-persona-store.vala:1905
+#: ../backends/eds/lib/edsf-persona-store.vala:1814
#: ../folks/role-details.vala:279
msgid "Roles are not writeable on this contact."
msgstr "Não é possível escrever os papeis deste contacto."
-#: ../backends/eds/lib/edsf-persona-store.vala:2006
-#: ../folks/name-details.vala:246
+#: ../backends/eds/lib/edsf-persona-store.vala:1915
+#: ../folks/name-details.vala:417
msgid "Structured name is not writeable on this contact."
msgstr "Não é possível escrever o nome estruturado deste contacto."
-#: ../backends/eds/lib/edsf-persona-store.vala:2045
+#: ../backends/eds/lib/edsf-persona-store.vala:1954
#: ../folks/im-details.vala:136
msgid "IM addresses are not writeable on this contact."
msgstr "Não é possível escrever os endereços de MI neste contacto."
-#: ../backends/eds/lib/edsf-persona-store.vala:2095
+#: ../backends/eds/lib/edsf-persona-store.vala:2004
#: ../folks/group-details.vala:174
msgid "Groups are not writeable on this contact."
msgstr "Não é possível escrever os grupos neste contacto."
-#: ../backends/eds/lib/edsf-persona-store.vala:2110
+#: ../backends/eds/lib/edsf-persona-store.vala:2019
msgid "My Contacts is only available for Google Contacts"
msgstr "Os Meus Contactos apenas estão disponíveis para o Google Contacts"
-#: ../backends/eds/lib/edsf-persona-store.vala:2181
+#: ../backends/eds/lib/edsf-persona-store.vala:2090
#: ../folks/gender-details.vala:79
msgid "Gender is not writeable on this contact."
msgstr "Não é possível escrever o género deste contacto."
-#: ../backends/eds/lib/edsf-persona-store.vala:2219
-#: ../folks/anti-linkable.vala:81
+#: ../backends/eds/lib/edsf-persona-store.vala:2128
+#: ../folks/anti-linkable.vala:84
msgid "Anti-links are not writeable on this contact."
msgstr "Não é possível escrever as antiassociações neste contacto."
-#: ../backends/eds/lib/edsf-persona-store.vala:2262
-#: ../folks/location-details.vala:129
+#: ../backends/eds/lib/edsf-persona-store.vala:2171
+#: ../folks/location-details.vala:135
msgid "Location is not writeable on this contact."
msgstr "Não é possível escrever a localização neste contacto."
#. Translators: the first parameter is a non-human-readable
#. * property name and the second parameter is an error
#. * message.
-#: ../backends/eds/lib/edsf-persona-store.vala:2439
+#: ../backends/eds/lib/edsf-persona-store.vala:2484
#, c-format
msgid "Property ‘%s’ is not writeable: %s"
msgstr "Não é possível escrever a propriedade ‘%s’: %s"
@@ -224,28 +300,28 @@ msgstr "Não é possível escrever a propriedade ‘%s’: %s"
#. Translators: the first parameter is a non-human-readable
#. * property name and the second parameter is an error
#. * message.
-#: ../backends/eds/lib/edsf-persona-store.vala:2448
+#: ../backends/eds/lib/edsf-persona-store.vala:2493
#, c-format
msgid "Invalid value for property ‘%s’: %s"
msgstr "Valor inválido para a propriedade ‘%s’: %s"
#. Translators: the first parameter is a non-human-readable
#. * property name and the second parameter is an error message.
-#: ../backends/eds/lib/edsf-persona-store.vala:2474
+#: ../backends/eds/lib/edsf-persona-store.vala:2519
#, c-format
msgid "Unknown error setting property ‘%s’: %s"
msgstr "Erro desconhecido ao definir a propriedade ‘%s’: %s"
#. Translators: the first parameter is a filename, and
#. * the second is an error message.
-#: ../backends/key-file/kf-persona-store.vala:233
+#: ../backends/key-file/kf-persona-store.vala:234
#, c-format
msgid "The relationship key file '%s' could not be loaded: %s"
msgstr "Não foi possível ler o ficheiro de chaves de relacionamento ‘%s’: %s"
#. Translators: the first parameter is a path, and the
#. * second is an error message.
-#: ../backends/key-file/kf-persona-store.vala:255
+#: ../backends/key-file/kf-persona-store.vala:256
#, c-format
msgid "The relationship key file directory '%s' could not be created: %s"
msgstr ""
@@ -254,14 +330,14 @@ msgstr ""
#. Translators: the first parameter is a filename, and
#. * the second is an error message.
-#: ../backends/key-file/kf-persona-store.vala:279
+#: ../backends/key-file/kf-persona-store.vala:280
#, c-format
msgid "The relationship key file '%s' could not be created: %s"
msgstr "Não foi possível criar o ficheiro de chaves de relacionamento '%s': %s"
#. Translators: the first parameter is a filename, the second is
#. * an error message.
-#: ../backends/key-file/kf-persona-store.vala:470
+#: ../backends/key-file/kf-persona-store.vala:471
#, c-format
msgid "Could not write updated key file '%s': %s"
msgstr "Incapaz de escrever o ficheiro de chaves atualizado '%s': %s"
@@ -271,13 +347,13 @@ msgstr "Incapaz de escrever o ficheiro de chaves atualizado '%s': %s"
#. * an IM address (e.g. “foo@jabber.org”), the second is
#. * the name of a protocol (e.g. “jabber”) and the third is
#. * an error message.
-#: ../backends/key-file/kf-persona.vala:172
+#: ../backends/key-file/kf-persona.vala:174
#, c-format
msgid "Invalid IM address ‘%s’ for protocol ‘%s’: %s"
msgstr "Endereço MI ‘%s’ inválido para o protocolo ‘%s’: %s"
#. Translators: the parameter is an error message.
-#: ../backends/key-file/kf-persona.vala:430
+#: ../backends/key-file/kf-persona.vala:432
#, c-format
msgid "Couldn't load data from key file: %s"
msgstr "Incapaz de ler dados do ficheiro de chaves: %s"
@@ -302,30 +378,28 @@ msgstr "Não foi encontrada a capacidade de contactos."
msgid "Error opening contacts view."
msgstr "Erro ao abrir a vista de contactos."
-#. Translators: the first parameter is the display name for
-#. * the Telepathy account, and the second is an error
-#. * message.
-#: ../backends/telepathy/lib/tpf-persona-store.vala:814
-#, c-format
+#: ../backends/ofono/ofono-backend.vala:196
msgid ""
-"Failed to determine whether we can set aliases on Telepathy account '%s': %s"
-msgstr ""
-"Falha ao determinar se é possível definir alias na conta Telepathy '%s': %s"
+"No oFono object manager running, so the oFono backend will be inactive. "
+"Either oFono isn’t installed or the service can’t be started."
+msgstr ""
+"Nenhum gestor de objetos oFono em execução, o motor oFono irá estar inativo. "
+"Ou o oFono não está instalado ou não foi possível iniciar o serviço."
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1278
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1248
msgid "Telepathy contacts representing the local user may not be removed."
msgstr ""
"Contactos Telepathy que representem o utilizador local poderão não ser "
"removidos."
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1289
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1259
#, c-format
msgid "Failed to remove a persona from store: %s"
msgstr "Falha ao remover uma persona do armazenamento: %s"
#. Translators: the first two parameters are store identifiers and
#. * the third is a contact identifier.
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1324
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1294
#, c-format
msgid ""
"Persona store (%s, %s) requires the following details:\n"
@@ -334,25 +408,25 @@ msgstr ""
"Armazenamento de personas (%s, %s) requer os seguintes detalhes:\n"
" contacto (disponibilizado: '%s')\n"
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1339
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1309
msgid "Cannot create a new Telepathy contact while offline."
msgstr "Incapaz de criar um novo contacto Telepathy estando desligado."
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1357
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1327
#, c-format
msgid "Failed to add a persona from details: %s"
msgstr "Falha ao adicionar uma persona a partir dos detalhes: %s"
#. Translators: "telepathy-logger" is the name of an application,
#. * and should not be translated.
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1377
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1347
msgid ""
"Failed to change favorite without a connection to the telepathy-logger "
"service."
msgstr ""
"Falha ao alterar o favorito sem uma ligação ao serviço telepathy-logger"
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1383
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1353
msgid ""
"Failed to change favorite status of Telepathy Persona because it has no "
"attached TpContact."
@@ -361,49 +435,49 @@ msgstr ""
"tem um TpContact associado."
#. Translators: the parameter is a contact identifier.
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1401
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1371
#, c-format
msgid "Failed to change favorite status for Telepathy contact ‘%s’."
msgstr "Falha ao alterar o estado de favorito do contacto Telepathy ‘%s’."
#. Translators: the parameter is an error message.
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1433
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1403
#, c-format
msgid "Failed to change contact's alias: %s"
msgstr "Falha al alterar o alias do contacto: %s"
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1514
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1484
msgid "Extended information may only be set on the user's Telepathy contact."
msgstr ""
"Informação extendida apenas pode ser definida no contacto Telepathy do "
"utilizador."
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1543
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1513
msgid ""
"Extended information cannot be written because the store is disconnected."
msgstr ""
"Não é possível escrever informação extendida pois o armazenamento está "
"desligado."
-#: ../backends/telepathy/lib/tpf-persona.vala:499
-#: ../backends/telepathy/lib/tpf-persona.vala:520
-#: ../backends/telepathy/lib/tpf-persona.vala:572
-#: ../backends/telepathy/lib/tpf-persona.vala:586
+#: ../backends/telepathy/lib/tpf-persona.vala:511
+#: ../backends/telepathy/lib/tpf-persona.vala:532
+#: ../backends/telepathy/lib/tpf-persona.vala:584
+#: ../backends/telepathy/lib/tpf-persona.vala:598
#, c-format
msgid "Failed to change group membership: %s"
msgstr "Falha ao alterar os membros do grupo: %s"
#. Translators: "account" refers to an instant messaging
#. * account.
-#: ../backends/telepathy/lib/tpf-persona.vala:502
-#: ../backends/telepathy/lib/tpf-persona.vala:575
+#: ../backends/telepathy/lib/tpf-persona.vala:514
+#: ../backends/telepathy/lib/tpf-persona.vala:587
msgid "Account is offline."
msgstr "A conta está em modo desligado."
#. Translators: the first parameter is the unknown key that
#. * was received with the details params, and the second
#. * identifies the persona store.
-#: ../backends/tracker/lib/trf-persona-store.vala:742
+#: ../backends/tracker/lib/trf-persona-store.vala:743
#, c-format
msgid "Unrecognized parameter '%s' passed to persona store '%s'."
msgstr "Parâmetro '%s' desconhecido passado ao armazenamento de personas '%s'."
@@ -414,19 +488,19 @@ msgstr "Alias não pode ser alterado neste contacto."
#. Translators: the first parameter is a folder path and the second
#. * is an error message.
-#: ../folks/backend-store.vala:627
+#: ../folks/backend-store.vala:651
#, c-format
msgid "Error listing contents of folder '%s': %s"
msgstr "Erro ao listar o conteúdo da pasta '%s': %s"
#. Translators: the parameter is a filename.
-#: ../folks/backend-store.vala:757
+#: ../folks/backend-store.vala:786
#, c-format
msgid "File or directory '%s' does not exist."
msgstr "O ficheiro ou diretório '%s' não existe."
#. Translators: the parameter is a filename.
-#: ../folks/backend-store.vala:763
+#: ../folks/backend-store.vala:792
#, c-format
msgid "Failed to get content type for '%s'."
msgstr "Falha ao obter o tipo de conteúdo de '%s'."
@@ -448,32 +522,32 @@ msgstr "Incapaz de compreeder o endereço de MI '%s'."
#. Translators: the first parameter is a persona store identifier
#. * and the second is an error message.
-#: ../folks/individual-aggregator.vala:935
+#: ../folks/individual-aggregator.vala:1040
#, c-format
msgid "Error preparing persona store '%s': %s"
msgstr "Erro ao preparar o armazenamento de personas '%s': %s"
#. Translators: the parameter is a property name.
-#: ../folks/individual-aggregator.vala:1158
-#: ../folks/individual-aggregator.vala:1386
+#: ../folks/individual-aggregator.vala:1269
+#: ../folks/individual-aggregator.vala:1536
#, c-format
msgid "Unknown property '%s' in linkable property list."
msgstr "Propriedade '%s' desconhecida na lista de propriedades associáveis."
#. Translators: the first parameter is a store identifier
#. * and the second parameter is an error message.
-#: ../folks/individual-aggregator.vala:1857
+#: ../folks/individual-aggregator.vala:2022
#, c-format
msgid "Failed to add contact for persona store ID '%s': %s"
msgstr ""
"Falha ao adicionar contacto no ID de armazenamento de personas '%s': %s"
-#: ../folks/individual-aggregator.vala:1958
+#: ../folks/individual-aggregator.vala:2119
msgid "Can’t link personas with no primary store."
msgstr "Incapaz de associar personas sem armazenamento primário."
-#: ../folks/individual-aggregator.vala:1959
-#: ../folks/individual-aggregator.vala:2291
+#: ../folks/individual-aggregator.vala:2120
+#: ../folks/individual-aggregator.vala:2451
#, c-format
msgid ""
"Persona store ‘%s:%s’ is configured as primary, but could not be found or "
@@ -482,8 +556,8 @@ msgstr ""
"Armazenamento de personas ‘%s:%s’ está configurado como primário, mas não "
"foi encontrado ou falhou a sua leitura."
-#: ../folks/individual-aggregator.vala:1960
-#: ../folks/individual-aggregator.vala:2292
+#: ../folks/individual-aggregator.vala:2121
+#: ../folks/individual-aggregator.vala:2452
#, c-format
msgid ""
"Check the relevant service is running, or change the default store in that "
@@ -492,31 +566,81 @@ msgstr ""
"Verifique que o serviço relevante se encontra em execução ou altere o "
"armazenamento por omissão nesse serviço ou utilizando a chave GSettings “%s”."
-#: ../folks/individual-aggregator.vala:1992
+#: ../folks/individual-aggregator.vala:2153
msgid "Anti-links can't be removed between personas being linked."
msgstr ""
"Antiassociações não pode ser removido entre personas que estão a ser "
"associadas"
-#: ../folks/individual-aggregator.vala:2290
+#: ../folks/individual-aggregator.vala:2450
msgid "Can’t add personas with no primary store."
msgstr "Incapaz de adicionar personas sem armazenamento primário."
-#: ../folks/individual-aggregator.vala:2301
+#: ../folks/individual-aggregator.vala:2461
#, c-format
msgid "Can't write to requested property (“%s”) of the writeable store."
msgstr ""
"Incapaz de alterar a propriedade pedida (“%s”) do armazenamento alterável."
-#: ../folks/individual.vala:217 ../folks/individual.vala:370
-#: ../folks/individual.vala:479 ../folks/individual.vala:730
-#: ../folks/individual.vala:808
+#: ../folks/individual.vala:216 ../folks/individual.vala:402
+#: ../folks/individual.vala:511 ../folks/individual.vala:762
+#: ../folks/individual.vala:840
#, c-format
msgid "Failed to change property ‘%s’: No suitable personas were found."
msgstr ""
"Falha ao alterar a propriedade ‘%s’: Não foram encontradas personas "
"adequadas."
+#. Translators: This is the default name for an Individual
+#. * when displayed in the UI if no personal details are available
+#. * for them.
+#: ../folks/individual.vala:1951
+msgid "Unnamed Person"
+msgstr "Pessoa Sem Nome"
+
+#. FIXME: Ideally we’d use a format string translated to the locale of the
+#. * persona whose name is being formatted, but no backend provides
+#. * information about personas’ locales, so we have to settle for the
+#. * current user’s locale.
+#. *
+#. * We thought about using nl_langinfo(_NL_NAME_NAME_FMT) here, but
+#. * decided against it because:
+#. * 1. It’s not the best documented API in the world, and its stability
+#. * is in question.
+#. * 2. An attempt to improve the interface in glibc met with a wall of
+#. * complaints: https://sourceware.org/bugzilla/show_bug.cgi?id=14641.
+#. *
+#. * However, we do re-use the string format placeholders from
+#. * _NL_NAME_NAME_FMT (as documented here:
+#. * http://lh.2xlibre.net/values/name_fmt/) because there’s a chance glibc
+#. * might eventually grow a useful interface for this.
+#. *
+#. * It does mean we have to implement our own parser for the name_fmt
+#. * format though, since glibc doesn’t provide a formatting function.
+#. Translators: This is a format string used to convert structured names
+#. * to a single string. It should be translated to the predominant
+#. * semi-formal name format for your locale, using the placeholders
+#. * documented here: http://lh.2xlibre.net/values/name_fmt/. You may be
+#. * able to re-use the existing glibc format string for your locale on that
+#. * page if it’s suitable.
+#. *
+#. * More explicitly: the supported placeholders are %f, %F, %g, %G, %m, %M,
+#. * %t. The romanisation modifier (e.g. %Rf) is recognized but ignored.
+#. * %s, %S and %d are all replaced by the same thing (the ‘Honorific
+#. * Prefixes’ from vCard) so please avoid using more than one.
+#. *
+#. * For example, the format string ‘%g%t%m%t%f’ expands to ‘John Andrew
+#. * Lees’ when used for a persona with first name ‘John’, additional names
+#. * ‘Andrew’ and family names ‘Lees’.
+#. *
+#. * If you need additional placeholders with other information or
+#. * punctuation, please file a bug against libfolks:
+#. * https://bugzilla.gnome.org/enter_bug.cgi?product=folks
+#.
+#: ../folks/name-details.vala:268
+msgid "%g%t%m%t%f"
+msgstr "%g%t%m%t%f"
+
#: ../folks/org.freedesktop.folks.gschema.xml.in.h:1
msgid "Primary store ID"
msgstr "ID do armazenamento primário"
@@ -537,35 +661,35 @@ msgstr ""
msgid "%s, %s, %s, %s, %s, %s, %s"
msgstr "%s, %s, %s, %s, %s, %s, %s"
-#: ../folks/presence-details.vala:159
+#: ../folks/presence-details.vala:171
msgid "Unknown status"
msgstr "Estado desconhecido"
-#: ../folks/presence-details.vala:161
+#: ../folks/presence-details.vala:173
msgid "Offline"
msgstr "Desligado"
-#: ../folks/presence-details.vala:165
+#: ../folks/presence-details.vala:177
msgid "Error"
msgstr "Erro"
-#: ../folks/presence-details.vala:167
+#: ../folks/presence-details.vala:179
msgid "Available"
msgstr "Disponível"
-#: ../folks/presence-details.vala:169
+#: ../folks/presence-details.vala:181
msgid "Away"
msgstr "Ausente"
-#: ../folks/presence-details.vala:171
+#: ../folks/presence-details.vala:183
msgid "Extended away"
msgstr "Ausente estendido"
-#: ../folks/presence-details.vala:173
+#: ../folks/presence-details.vala:185
msgid "Busy"
msgstr "Ocupado"
-#: ../folks/presence-details.vala:175
+#: ../folks/presence-details.vala:187
msgid "Hidden"
msgstr "Escondido"
@@ -667,54 +791,54 @@ msgstr "Nome do motor de origem (omissão: 'pidgin')"
msgid "Source filename (default: specific to source backend)"
msgstr "Nome do ficheiro de origem (omissão: específico do motor de origem)"
-#: ../tools/import.vala:57
+#: ../tools/import.vala:58
msgid "— import meta-contact information to libfolks"
msgstr "— importar informação de meta-contacto para o libfolks"
#. Translators: the parameter is an error message.
-#: ../tools/import.vala:67
+#: ../tools/import.vala:68
#, c-format
msgid "Couldn't parse command line options: %s"
msgstr "Incapaz de processar opções de linha de comando: %s"
#. Translators: the parameter is an error message.
-#: ../tools/import.vala:108
+#: ../tools/import.vala:109
#, c-format
msgid "Couldn't load the backends: %s"
msgstr "Incapaz de ler os motores: %s"
#. Translators: the parameter is a backend identifier.
-#: ../tools/import.vala:119
+#: ../tools/import.vala:120
#, c-format
msgid "Couldn't load the ‘%s’ backend."
msgstr "Incapaz de ler o motor ‘%s’."
#. Translators: the first parameter is a backend identifier and the
#. * second parameter is an error message.
-#: ../tools/import.vala:132
+#: ../tools/import.vala:133
#, c-format
msgid "Couldn't prepare the ‘%s’ backend: %s"
msgstr "Incapaz de preparar o motor ‘%s’: %s"
#. Translators: the parameter is a backend identifier.
-#: ../tools/import.vala:145
+#: ../tools/import.vala:146
#, c-format
msgid "Couldn't load the ‘%s’ backend's persona store."
msgstr "Incapaz de ler o armazenamento de personas do motor ‘%s’."
-#: ../tools/import.vala:166
+#: ../tools/import.vala:167
#, c-format
msgid "Couldn't prepare the ‘%s’ backend's persona store: %s"
msgstr "Incapaz de preparar o armazenamento de personas do motor ‘%s’: %s"
#. Translators: the parameter is an error message.
-#: ../tools/import.vala:184
+#: ../tools/import.vala:185
#, c-format
msgid "Error importing contacts: %s"
msgstr "Erro ao importar contactos: %s"
#. Translators: both parameters are identifiers for backends.
-#: ../tools/import.vala:198
+#: ../tools/import.vala:199
#, c-format
msgid ""
"Unrecognized source backend name ‘%s’. ‘%s’ is currently the only supported "
diff --git a/po/ru.po b/po/ru.po
index 0e876663..3df703ed 100644
--- a/po/ru.po
+++ b/po/ru.po
@@ -10,9 +10,9 @@ msgstr ""
"Project-Id-Version: folks master\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?"
"product=folks&keywords=I18N+L10N&component=general\n"
-"POT-Creation-Date: 2013-03-20 16:54+0000\n"
-"PO-Revision-Date: 2013-03-17 23:04+0400\n"
-"Last-Translator: Dmitriy S. Seregin <dseregin@59.ru>\n"
+"POT-Creation-Date: 2014-03-10 05:56+0000\n"
+"PO-Revision-Date: 2014-03-10 21:25+0300\n"
+"Last-Translator: Yuri Myasoedov <omerta13@yandex.ru>\n"
"Language-Team: русский <gnome-cyr@gnome.org>\n"
"Language: ru\n"
"MIME-Version: 1.0\n"
@@ -20,7 +20,82 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
-"X-Generator: Poedit 1.5.5\n"
+"X-Generator: Poedit 1.5.4\n"
+
+#: ../backends/bluez/bluez-backend.vala:600
+msgid ""
+"No BlueZ 5 object manager running, so the BlueZ backend will be inactive. "
+"Either your BlueZ installation is too old (only version 5 is supported) or "
+"the service can’t be started."
+msgstr ""
+"Диспетчер объектов BlueZ 5 не запущен, BlueZ будет неактивен. Версия BlueZ "
+"слишком старая (поддерживается только версия 5) или служба не может быть "
+"запущена."
+
+#: ../backends/bluez/bluez-backend.vala:613
+msgid ""
+"Error connecting to OBEX transfer daemon over D-Bus. Ensure BlueZ and obexd "
+"are installed."
+msgstr ""
+"Ошибка подключения к службе передачи OBEX через D-Bus. Убедитесь, что BlueZ "
+"и obexd установлены."
+
+#. Translators: the parameter is an error message.
+#: ../backends/bluez/bluez-persona-store.vala:385
+#, c-format
+msgid "Error reading the transferred address book file: %s"
+msgstr "Ошибка чтения переданного файла адресной книги: %s"
+
+#. Translators: the first parameter is the name of the
+#. * failed transfer, and the second is a Bluetooth device
+#. * alias.
+#. Translators: the first parameter is the name of the failed
+#. * transfer, and the second is a Bluetooth device alias.
+#: ../backends/bluez/bluez-persona-store.vala:667
+#: ../backends/bluez/bluez-persona-store.vala:689
+#, c-format
+msgid ""
+"Error during transfer of the address book ‘%s’ from Bluetooth device ‘%s’."
+msgstr ""
+"Ошибка во время передачи адресной книги «%s» с Bluetooth-устройства «%s»."
+
+#: ../backends/bluez/bluez-persona-store.vala:782
+#, c-format
+msgid ""
+"Permission to access the address book on Bluetooth device ‘%s’ was denied by "
+"the user."
+msgstr ""
+"Доступ к адресной книге на Bluetooth-устройстве «%s» запрещён пользователем."
+
+#. Translators: the first parameter is a Bluetooth device
+#. * alias, and the second is an error message.
+#: ../backends/bluez/bluez-persona-store.vala:789
+#, c-format
+msgid "An OBEX address book transfer from device ‘%s’ could not be started: %s"
+msgstr ""
+"Не удалось запустить OBEX-передачу адресной книги с устройства «%s»: %s"
+
+#. Translators: the first parameter is a Bluetooth device
+#. * alias, and the second is an error message.
+#: ../backends/bluez/bluez-persona-store.vala:829
+#, c-format
+msgid "The OBEX address book transfer from device ‘%s’ failed: %s"
+msgstr ""
+"Не удалось выполнить OBEX-передачу адресной книги с устройства «%s»: %s"
+
+#. Translators: the first parameter is a Bluetooth device
+#. * alias, and the second is an error message.
+#: ../backends/bluez/bluez-persona-store.vala:846
+#, c-format
+msgid ""
+"Error during transfer of the address book from Bluetooth device ‘%s’: %s"
+msgstr ""
+"Ошибка во время передачи адресной книги с Bluetooth-устройства «%s»: %s"
+
+#: ../backends/bluez/bluez-persona-store.vala:1064
+#, c-format
+msgid "Bluetooth device ‘%s’ disappeared during address book transfer."
+msgstr "Bluetooth-устройство «%s» пропало во время передачи адресной книги."
# данная группа контактов не переведена в Google Контакты, значит оставляем не переведенной и тут, по просьбе разрабов folks
#. The timeout after which we consider a property change to have failed if we
@@ -37,7 +112,7 @@ msgstr "Starred in Android"
#. Translators: the first parameter is an address book
#. * URI and the second is a persona UID.
-#: ../backends/eds/lib/edsf-persona-store.vala:671
+#: ../backends/eds/lib/edsf-persona-store.vala:673
#, c-format
msgid "Address book ‘%s’ is offline, so contact ‘%s’ cannot be removed."
msgstr ""
@@ -46,61 +121,61 @@ msgstr ""
#. Translators: the first parameter is an address book
#. * URI and the second is an error message.
-#: ../backends/eds/lib/edsf-persona-store.vala:677
+#: ../backends/eds/lib/edsf-persona-store.vala:679
#, c-format
msgid "Permission denied to remove contact ‘%s’: %s"
msgstr "Отказано в разрешении на удаление контакта «%s»: %s"
#. Translators: the parameter is an error message.
-#: ../backends/eds/lib/edsf-persona-store.vala:682
+#: ../backends/eds/lib/edsf-persona-store.vala:684
#, c-format
msgid "Removing contacts isn't supported by this persona store: %s"
msgstr "Удаление контактов не поддерживается этим персональным хранилищем: %s"
-#: ../backends/eds/lib/edsf-persona-store.vala:711
+#: ../backends/eds/lib/edsf-persona-store.vala:713
#, c-format
msgid "Can't remove contact ‘%s’: %s"
msgstr "Не удалось удалить контакт «%s»: %s"
#. Translators: the parameter is an address book
#. * URI.
-#: ../backends/eds/lib/edsf-persona-store.vala:801
-#: ../backends/eds/lib/edsf-persona-store.vala:992
+#: ../backends/eds/lib/edsf-persona-store.vala:802
+#: ../backends/eds/lib/edsf-persona-store.vala:993
#, c-format
msgid "Address book ‘%s’ is offline."
msgstr "Адресная книга «%s» работает в автономном режиме."
#. Translators: the first parameter is an address
#. * book URI and the second is an error message.
-#: ../backends/eds/lib/edsf-persona-store.vala:806
-#: ../backends/eds/lib/edsf-persona-store.vala:997
+#: ../backends/eds/lib/edsf-persona-store.vala:807
+#: ../backends/eds/lib/edsf-persona-store.vala:998
#, c-format
msgid "Permission denied to open address book ‘%s’: %s"
msgstr "Отказано в разрешении на открытие адресной книги «%s»: %s"
#. Translators: the first parameter is an address book URI
#. * and the second is an error message.
-#: ../backends/eds/lib/edsf-persona-store.vala:839
+#: ../backends/eds/lib/edsf-persona-store.vala:840
#, c-format
msgid "Couldn't open address book ‘%s’: %s"
msgstr "Не удаётся открыть адресную книгу «%s»: %s"
#. Translators: the parameteter is an error message.
-#: ../backends/eds/lib/edsf-persona-store.vala:905
-#: ../backends/eds/lib/edsf-persona-store.vala:935
+#: ../backends/eds/lib/edsf-persona-store.vala:906
+#: ../backends/eds/lib/edsf-persona-store.vala:936
#, c-format
msgid "Couldn't get address book capabilities: %s"
msgstr "Не удалось получить возможности адресной книги: %s"
#. Translators: the parameter is an address book URI.
-#: ../backends/eds/lib/edsf-persona-store.vala:951
+#: ../backends/eds/lib/edsf-persona-store.vala:952
#, c-format
msgid "Couldn't get view for address book ‘%s’."
msgstr "Не удалось показать адресную книгу «%s»."
#. Translators: the first parameter is an address book URI
#. * and the second is an error message.
-#: ../backends/eds/lib/edsf-persona-store.vala:1030
+#: ../backends/eds/lib/edsf-persona-store.vala:1031
#, c-format
msgid "Couldn't get view for address book ‘%s’: %s"
msgstr "Не удалось показать адресную книгу «%s»: %s"
@@ -108,121 +183,121 @@ msgstr "Не удалось показать адресную книгу «%s»:
#. Translators: the parameter is the name of a property on a
#. * contact, formatted in the normal GObject style (e.g.
#. * lowercase with hyphens to separate words).
-#: ../backends/eds/lib/edsf-persona-store.vala:1390
+#: ../backends/eds/lib/edsf-persona-store.vala:1303
#, c-format
msgid "Changing the ‘%s’ property failed due to reaching the timeout."
msgstr "Не удалось изменить свойство «%s» из-за превышения лимита времени."
-#: ../backends/eds/lib/edsf-persona-store.vala:1428
+#: ../backends/eds/lib/edsf-persona-store.vala:1337
#: ../folks/avatar-details.vala:63
msgid "Avatar is not writeable on this contact."
msgstr "В этот контакт нельзя записать аватар."
-#: ../backends/eds/lib/edsf-persona-store.vala:1449
+#: ../backends/eds/lib/edsf-persona-store.vala:1358
#: ../folks/web-service-details.vala:123
msgid "Web service addresses are not writeable on this contact."
msgstr "В этот контакт нельзя записать адреса веб-служб."
-#: ../backends/eds/lib/edsf-persona-store.vala:1485
+#: ../backends/eds/lib/edsf-persona-store.vala:1394
#: ../folks/url-details.vala:152
msgid "URLs are not writeable on this contact."
msgstr "В этот контакт нельзя записать URL."
-#: ../backends/eds/lib/edsf-persona-store.vala:1566
+#: ../backends/eds/lib/edsf-persona-store.vala:1475
#: ../folks/local-id-details.vala:64
msgid "Local IDs are not writeable on this contact."
msgstr "В этот контакт нельзя записать локальный идентификатор."
-#: ../backends/eds/lib/edsf-persona-store.vala:1595
+#: ../backends/eds/lib/edsf-persona-store.vala:1504
msgid "The contact cannot be marked as favourite."
msgstr "Контакт нельзя сделать избранным."
#. Translators: the parameter is an error message.
-#: ../backends/eds/lib/edsf-persona-store.vala:1667
+#: ../backends/eds/lib/edsf-persona-store.vala:1576
#, c-format
msgid "Can't update avatar: %s"
msgstr "Не удалось обновить аватар: %s"
-#: ../backends/eds/lib/edsf-persona-store.vala:1678
+#: ../backends/eds/lib/edsf-persona-store.vala:1587
#: ../folks/email-details.vala:120
msgid "E-mail addresses are not writeable on this contact."
msgstr "В этот контакт нельзя записывать адреса эл. почты."
-#: ../backends/eds/lib/edsf-persona-store.vala:1696
-#: ../folks/phone-details.vala:224
+#: ../backends/eds/lib/edsf-persona-store.vala:1605
+#: ../folks/phone-details.vala:255
msgid "Phone numbers are not writeable on this contact."
msgstr "В этот контакт нельзя записывать телефонные номера."
-#: ../backends/eds/lib/edsf-persona-store.vala:1714
+#: ../backends/eds/lib/edsf-persona-store.vala:1623
#: ../folks/postal-address-details.vala:361
msgid "Postal addresses are not writeable on this contact."
msgstr "В этот контакт нельзя записывать почтовые адреса."
-#: ../backends/eds/lib/edsf-persona-store.vala:1785
-#: ../folks/name-details.vala:283
+#: ../backends/eds/lib/edsf-persona-store.vala:1694
+#: ../folks/name-details.vala:454
msgid "Full name is not writeable on this contact."
msgstr "В этот контакт нельзя записать полное имя."
-#: ../backends/eds/lib/edsf-persona-store.vala:1807
-#: ../folks/name-details.vala:321
+#: ../backends/eds/lib/edsf-persona-store.vala:1716
+#: ../folks/name-details.vala:492
msgid "Nickname is not writeable on this contact."
msgstr "В этот контакт нельзя записать псевдоним."
-#: ../backends/eds/lib/edsf-persona-store.vala:1829
+#: ../backends/eds/lib/edsf-persona-store.vala:1738
#: ../folks/note-details.vala:138
msgid "Notes are not writeable on this contact."
msgstr "В этот контакт нельзя записать примечание."
-#: ../backends/eds/lib/edsf-persona-store.vala:1861
+#: ../backends/eds/lib/edsf-persona-store.vala:1770
#: ../folks/birthday-details.vala:62
msgid "Birthday is not writeable on this contact."
msgstr "В этот контакт нельзя записать день рождения."
-#: ../backends/eds/lib/edsf-persona-store.vala:1905
+#: ../backends/eds/lib/edsf-persona-store.vala:1814
#: ../folks/role-details.vala:279
msgid "Roles are not writeable on this contact."
msgstr "В этот контакт нельзя записывать роли."
-#: ../backends/eds/lib/edsf-persona-store.vala:2006
-#: ../folks/name-details.vala:246
+#: ../backends/eds/lib/edsf-persona-store.vala:1915
+#: ../folks/name-details.vala:417
msgid "Structured name is not writeable on this contact."
msgstr "В этот контакт нельзя записывать структурированные имена."
-#: ../backends/eds/lib/edsf-persona-store.vala:2045
+#: ../backends/eds/lib/edsf-persona-store.vala:1954
#: ../folks/im-details.vala:136
msgid "IM addresses are not writeable on this contact."
msgstr ""
"В этот контакт нельзя записывать адреса клиентов для обмена мгновенными "
"сообщениями."
-#: ../backends/eds/lib/edsf-persona-store.vala:2095
+#: ../backends/eds/lib/edsf-persona-store.vala:2004
#: ../folks/group-details.vala:174
msgid "Groups are not writeable on this contact."
msgstr "В этот контакт нельзя записывать группы."
-#: ../backends/eds/lib/edsf-persona-store.vala:2110
+#: ../backends/eds/lib/edsf-persona-store.vala:2019
msgid "My Contacts is only available for Google Contacts"
msgstr "Мои контакты доступны только из Контактов Google"
-#: ../backends/eds/lib/edsf-persona-store.vala:2181
+#: ../backends/eds/lib/edsf-persona-store.vala:2090
#: ../folks/gender-details.vala:79
msgid "Gender is not writeable on this contact."
msgstr "В этот контакт нельзя записать пол."
-#: ../backends/eds/lib/edsf-persona-store.vala:2219
-#: ../folks/anti-linkable.vala:81
+#: ../backends/eds/lib/edsf-persona-store.vala:2128
+#: ../folks/anti-linkable.vala:84
msgid "Anti-links are not writeable on this contact."
msgstr "В этот контакт нельзя записывать антиссылки."
-#: ../backends/eds/lib/edsf-persona-store.vala:2262
-#: ../folks/location-details.vala:129
+#: ../backends/eds/lib/edsf-persona-store.vala:2171
+#: ../folks/location-details.vala:135
msgid "Location is not writeable on this contact."
msgstr "Расположение не возможно записать в этот контакт."
#. Translators: the first parameter is a non-human-readable
#. * property name and the second parameter is an error
#. * message.
-#: ../backends/eds/lib/edsf-persona-store.vala:2439
+#: ../backends/eds/lib/edsf-persona-store.vala:2484
#, c-format
msgid "Property ‘%s’ is not writeable: %s"
msgstr "Свойство «%s» с недоступно для записи: %s"
@@ -230,42 +305,42 @@ msgstr "Свойство «%s» с недоступно для записи: %s"
#. Translators: the first parameter is a non-human-readable
#. * property name and the second parameter is an error
#. * message.
-#: ../backends/eds/lib/edsf-persona-store.vala:2448
+#: ../backends/eds/lib/edsf-persona-store.vala:2493
#, c-format
msgid "Invalid value for property ‘%s’: %s"
msgstr "Неверное значение свойства «%s»: %s"
#. Translators: the first parameter is a non-human-readable
#. * property name and the second parameter is an error message.
-#: ../backends/eds/lib/edsf-persona-store.vala:2474
+#: ../backends/eds/lib/edsf-persona-store.vala:2519
#, c-format
msgid "Unknown error setting property ‘%s’: %s"
msgstr "Неизвестная ошибка при установке свойства «%s»: %s"
#. Translators: the first parameter is a filename, and
#. * the second is an error message.
-#: ../backends/key-file/kf-persona-store.vala:233
+#: ../backends/key-file/kf-persona-store.vala:234
#, c-format
msgid "The relationship key file '%s' could not be loaded: %s"
msgstr "Файл сопутствующего ключа «%s» не может быть загружен: %s"
#. Translators: the first parameter is a path, and the
#. * second is an error message.
-#: ../backends/key-file/kf-persona-store.vala:255
+#: ../backends/key-file/kf-persona-store.vala:256
#, c-format
msgid "The relationship key file directory '%s' could not be created: %s"
msgstr "Каталог файла сопутствующего ключа «%s» не может быть создан: %s"
#. Translators: the first parameter is a filename, and
#. * the second is an error message.
-#: ../backends/key-file/kf-persona-store.vala:279
+#: ../backends/key-file/kf-persona-store.vala:280
#, c-format
msgid "The relationship key file '%s' could not be created: %s"
msgstr "Файл сопутствующего ключа «%s» не может быть создан: %s"
#. Translators: the first parameter is a filename, the second is
#. * an error message.
-#: ../backends/key-file/kf-persona-store.vala:470
+#: ../backends/key-file/kf-persona-store.vala:471
#, c-format
msgid "Could not write updated key file '%s': %s"
msgstr "Не удалось записать обновлённый файл ключа «%s»: %s"
@@ -275,13 +350,13 @@ msgstr "Не удалось записать обновлённый файл к
#. * an IM address (e.g. “foo@jabber.org”), the second is
#. * the name of a protocol (e.g. “jabber”) and the third is
#. * an error message.
-#: ../backends/key-file/kf-persona.vala:172
+#: ../backends/key-file/kf-persona.vala:174
#, c-format
msgid "Invalid IM address ‘%s’ for protocol ‘%s’: %s"
msgstr "Неверный адрес IM «%s» для протокола «%s»: %s"
#. Translators: the parameter is an error message.
-#: ../backends/key-file/kf-persona.vala:430
+#: ../backends/key-file/kf-persona.vala:432
#, c-format
msgid "Couldn't load data from key file: %s"
msgstr "Не удалось загрузить данные из файла ключа: %s"
@@ -306,30 +381,27 @@ msgstr "Не найдены возможности контактов."
msgid "Error opening contacts view."
msgstr "Ошибка при открытии списка контактов."
-#. Translators: the first parameter is the display name for
-#. * the Telepathy account, and the second is an error
-#. * message.
-#: ../backends/telepathy/lib/tpf-persona-store.vala:814
-#, c-format
+#: ../backends/ofono/ofono-backend.vala:196
msgid ""
-"Failed to determine whether we can set aliases on Telepathy account '%s': %s"
+"No oFono object manager running, so the oFono backend will be inactive. "
+"Either oFono isn’t installed or the service can’t be started."
msgstr ""
-"Не удалось определить возможность установки псевдонима на учётной записи "
-"Telepathy '%s': %s"
+"Диспетчер объектов oFono не запущен, oFono будет неактивен. Версия oFono "
+"слишком старая или служба не может быть запущена."
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1278
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1248
msgid "Telepathy contacts representing the local user may not be removed."
msgstr ""
"Нельзя удалить контакты Telepathy, представляющие локального пользователя."
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1289
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1259
#, c-format
msgid "Failed to remove a persona from store: %s"
msgstr "Не удалось удалить контакт из хранилища: %s"
#. Translators: the first two parameters are store identifiers and
#. * the third is a contact identifier.
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1324
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1294
#, c-format
msgid ""
"Persona store (%s, %s) requires the following details:\n"
@@ -338,18 +410,18 @@ msgstr ""
"Хранилищу (%s, %s) требуются следущие сведения:\n"
" контакт (идентификатор: «%s»)\n"
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1339
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1309
msgid "Cannot create a new Telepathy contact while offline."
msgstr "Невозможно создать новый контакт Telepathy в автономном режиме"
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1357
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1327
#, c-format
msgid "Failed to add a persona from details: %s"
msgstr "Не удалось добавить контакт из дополнительной информации: %s"
#. Translators: "telepathy-logger" is the name of an application,
#. * and should not be translated.
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1377
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1347
msgid ""
"Failed to change favorite without a connection to the telepathy-logger "
"service."
@@ -357,7 +429,7 @@ msgstr ""
"Не удалось изменить статус избранности без подключения к службе telepathy-"
"logger."
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1383
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1353
msgid ""
"Failed to change favorite status of Telepathy Persona because it has no "
"attached TpContact."
@@ -366,49 +438,49 @@ msgstr ""
"прикреплённого объекта TpContact."
#. Translators: the parameter is a contact identifier.
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1401
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1371
#, c-format
msgid "Failed to change favorite status for Telepathy contact ‘%s’."
msgstr "Не удалось изменить состояние избранности для контакта Telepathy «%s»."
#. Translators: the parameter is an error message.
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1433
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1403
#, c-format
msgid "Failed to change contact's alias: %s"
msgstr "Не удалось изменить псевдоним контакта: %s"
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1514
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1484
msgid "Extended information may only be set on the user's Telepathy contact."
msgstr ""
"Дополнительная информация может быть установлена только для "
"пользовательского контакта Telepathy."
-#: ../backends/telepathy/lib/tpf-persona-store.vala:1543
+#: ../backends/telepathy/lib/tpf-persona-store.vala:1513
msgid ""
"Extended information cannot be written because the store is disconnected."
msgstr ""
"Дополнительная информация не может быть записана из-за отсутствия "
"подключения к хранилищу."
-#: ../backends/telepathy/lib/tpf-persona.vala:499
-#: ../backends/telepathy/lib/tpf-persona.vala:520
-#: ../backends/telepathy/lib/tpf-persona.vala:572
-#: ../backends/telepathy/lib/tpf-persona.vala:586
+#: ../backends/telepathy/lib/tpf-persona.vala:511
+#: ../backends/telepathy/lib/tpf-persona.vala:532
+#: ../backends/telepathy/lib/tpf-persona.vala:584
+#: ../backends/telepathy/lib/tpf-persona.vala:598
#, c-format
msgid "Failed to change group membership: %s"
msgstr "Не удалось изменить членство в группе: %s"
#. Translators: "account" refers to an instant messaging
#. * account.
-#: ../backends/telepathy/lib/tpf-persona.vala:502
-#: ../backends/telepathy/lib/tpf-persona.vala:575
+#: ../backends/telepathy/lib/tpf-persona.vala:514
+#: ../backends/telepathy/lib/tpf-persona.vala:587
msgid "Account is offline."
msgstr "Учётная запись находится в автономном режиме."
#. Translators: the first parameter is the unknown key that
#. * was received with the details params, and the second
#. * identifies the persona store.
-#: ../backends/tracker/lib/trf-persona-store.vala:742
+#: ../backends/tracker/lib/trf-persona-store.vala:743
#, c-format
msgid "Unrecognized parameter '%s' passed to persona store '%s'."
msgstr "В личное хранилище «%s» передан нераспознанный параметр «%s»."
@@ -419,19 +491,19 @@ msgstr "Нельзя записать псевдоним для этого ко
#. Translators: the first parameter is a folder path and the second
#. * is an error message.
-#: ../folks/backend-store.vala:627
+#: ../folks/backend-store.vala:651
#, c-format
msgid "Error listing contents of folder '%s': %s"
msgstr "Не удалось получить содержимого папки «%s»: %s"
#. Translators: the parameter is a filename.
-#: ../folks/backend-store.vala:757
+#: ../folks/backend-store.vala:786
#, c-format
msgid "File or directory '%s' does not exist."
msgstr "Файл или каталог «%s» не существует."
#. Translators: the parameter is a filename.
-#: ../folks/backend-store.vala:763
+#: ../folks/backend-store.vala:792
#, c-format
msgid "Failed to get content type for '%s'."
msgstr "Не удалось получить тип содержимого для «%s»."
@@ -453,31 +525,31 @@ msgstr "Не удалось разобрать адрес «%s»."
#. Translators: the first parameter is a persona store identifier
#. * and the second is an error message.
-#: ../folks/individual-aggregator.vala:935
+#: ../folks/individual-aggregator.vala:1040
#, c-format
msgid "Error preparing persona store '%s': %s"
msgstr "Ошибка при подготовке хранилища контакта «%s»: %s"
#. Translators: the parameter is a property name.
-#: ../folks/individual-aggregator.vala:1158
-#: ../folks/individual-aggregator.vala:1386
+#: ../folks/individual-aggregator.vala:1269
+#: ../folks/individual-aggregator.vala:1536
#, c-format
msgid "Unknown property '%s' in linkable property list."
msgstr "Неизвестное свойство «%s» в ссылочном списке свойств."
#. Translators: the first parameter is a store identifier
#. * and the second parameter is an error message.
-#: ../folks/individual-aggregator.vala:1857
+#: ../folks/individual-aggregator.vala:2022
#, c-format
msgid "Failed to add contact for persona store ID '%s': %s"
msgstr "Не удалось добавить контакт для хранилища с идентификатором «%s»: %s"
-#: ../folks/individual-aggregator.vala:1958
+#: ../folks/individual-aggregator.vala:2119
msgid "Can’t link personas with no primary store."
msgstr "Невозможно связать контакты без основного хранилища."
-#: ../folks/individual-aggregator.vala:1959
-#: ../folks/individual-aggregator.vala:2291
+#: ../folks/individual-aggregator.vala:2120
+#: ../folks/individual-aggregator.vala:2451
#, c-format
msgid ""
"Persona store ‘%s:%s’ is configured as primary, but could not be found or "
@@ -486,8 +558,8 @@ msgstr ""
"Хранилище «%s:%s» настроено как главное, но его не удалось найти или "
"загрузить."
-#: ../folks/individual-aggregator.vala:1960
-#: ../folks/individual-aggregator.vala:2292
+#: ../folks/individual-aggregator.vala:2121
+#: ../folks/individual-aggregator.vala:2452
#, c-format
msgid ""
"Check the relevant service is running, or change the default store in that "
@@ -496,27 +568,78 @@ msgstr ""
"Проверьте, запущена ли соответствующая служба, или измените хранилище по "
"умолчанию в этой службе, или воспользуйтесь ключом GSettings «%s»."
-#: ../folks/individual-aggregator.vala:1992
+#: ../folks/individual-aggregator.vala:2153
msgid "Anti-links can't be removed between personas being linked."
msgstr "Нельзя удалять антиссылки между связываемыми контактами."
-#: ../folks/individual-aggregator.vala:2290
+#: ../folks/individual-aggregator.vala:2450
msgid "Can’t add personas with no primary store."
msgstr "Невозможно добавить контакты без основного хранилища."
-#: ../folks/individual-aggregator.vala:2301
+#: ../folks/individual-aggregator.vala:2461
#, c-format
msgid "Can't write to requested property (“%s”) of the writeable store."
msgstr "Не удалось выполнить запись в запрошенное свойство («%s») хранилища."
-#: ../folks/individual.vala:217 ../folks/individual.vala:370
-#: ../folks/individual.vala:479 ../folks/individual.vala:730
-#: ../folks/individual.vala:808
+#: ../folks/individual.vala:216 ../folks/individual.vala:402
+#: ../folks/individual.vala:511 ../folks/individual.vala:762
+#: ../folks/individual.vala:840
#, c-format
msgid "Failed to change property ‘%s’: No suitable personas were found."
msgstr ""
"Не удалось изменить свойство «%s»: не найдено соответствующих контактов."
+#. Translators: This is the default name for an Individual
+#. * when displayed in the UI if no personal details are available
+#. * for them.
+#: ../folks/individual.vala:1951
+msgid "Unnamed Person"
+msgstr "Безымянный контакт"
+
+# http://lh.2xlibre.net/values/name_fmt/
+#. FIXME: Ideally we’d use a format string translated to the locale of the
+#. * persona whose name is being formatted, but no backend provides
+#. * information about personas’ locales, so we have to settle for the
+#. * current user’s locale.
+#. *
+#. * We thought about using nl_langinfo(_NL_NAME_NAME_FMT) here, but
+#. * decided against it because:
+#. * 1. It’s not the best documented API in the world, and its stability
+#. * is in question.
+#. * 2. An attempt to improve the interface in glibc met with a wall of
+#. * complaints: https://sourceware.org/bugzilla/show_bug.cgi?id=14641.
+#. *
+#. * However, we do re-use the string format placeholders from
+#. * _NL_NAME_NAME_FMT (as documented here:
+#. * http://lh.2xlibre.net/values/name_fmt/) because there’s a chance glibc
+#. * might eventually grow a useful interface for this.
+#. *
+#. * It does mean we have to implement our own parser for the name_fmt
+#. * format though, since glibc doesn’t provide a formatting function.
+#. Translators: This is a format string used to convert structured names
+#. * to a single string. It should be translated to the predominant
+#. * semi-formal name format for your locale, using the placeholders
+#. * documented here: http://lh.2xlibre.net/values/name_fmt/. You may be
+#. * able to re-use the existing glibc format string for your locale on that
+#. * page if it’s suitable.
+#. *
+#. * More explicitly: the supported placeholders are %f, %F, %g, %G, %m, %M,
+#. * %t. The romanisation modifier (e.g. %Rf) is recognized but ignored.
+#. * %s, %S and %d are all replaced by the same thing (the ‘Honorific
+#. * Prefixes’ from vCard) so please avoid using more than one.
+#. *
+#. * For example, the format string ‘%g%t%m%t%f’ expands to ‘John Andrew
+#. * Lees’ when used for a persona with first name ‘John’, additional names
+#. * ‘Andrew’ and family names ‘Lees’.
+#. *
+#. * If you need additional placeholders with other information or
+#. * punctuation, please file a bug against libfolks:
+#. * https://bugzilla.gnome.org/enter_bug.cgi?product=folks
+#.
+#: ../folks/name-details.vala:268
+msgid "%g%t%m%t%f"
+msgstr "%d%t%g%t%m%t%f"
+
#: ../folks/org.freedesktop.folks.gschema.xml.in.h:1
msgid "Primary store ID"
msgstr "ID основного хранилища"
@@ -537,35 +660,35 @@ msgstr ""
msgid "%s, %s, %s, %s, %s, %s, %s"
msgstr "%s, %s, %s, %s, %s, %s, %s"
-#: ../folks/presence-details.vala:159
+#: ../folks/presence-details.vala:171
msgid "Unknown status"
msgstr "Неизвестный статус"
-#: ../folks/presence-details.vala:161
+#: ../folks/presence-details.vala:173
msgid "Offline"
msgstr "Не в сети"
-#: ../folks/presence-details.vala:165
+#: ../folks/presence-details.vala:177
msgid "Error"
msgstr "Ошибка"
-#: ../folks/presence-details.vala:167
+#: ../folks/presence-details.vala:179
msgid "Available"
msgstr "В сети"
-#: ../folks/presence-details.vala:169
+#: ../folks/presence-details.vala:181
msgid "Away"
msgstr "Отсутствует"
-#: ../folks/presence-details.vala:171
+#: ../folks/presence-details.vala:183
msgid "Extended away"
msgstr "Давно отсутствует"
-#: ../folks/presence-details.vala:173
+#: ../folks/presence-details.vala:185
msgid "Busy"
msgstr "Занят"
-#: ../folks/presence-details.vala:175
+#: ../folks/presence-details.vala:187
msgid "Hidden"
msgstr "Невидимый"
@@ -722,3 +845,10 @@ msgid ""
msgstr ""
"Нераспознанное имя драйвера источника «%s». «%s» в настоящий момент является "
"единственным поддерживаемым драйвером источника."
+
+#~ msgid ""
+#~ "Failed to determine whether we can set aliases on Telepathy account '%s': "
+#~ "%s"
+#~ msgstr ""
+#~ "Не удалось определить возможность установки псевдонима на учётной записи "
+#~ "Telepathy '%s': %s"
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 2fad8ce4..38561942 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -8,6 +8,12 @@ SUBDIRS = \
tools \
$(NULL)
+if ENABLE_BLUEZ
+if HAVE_BLUEZ_TESTS
+SUBDIRS += bluez
+endif
+endif
+
if ENABLE_TELEPATHY
SUBDIRS += folks telepathy
endif
@@ -34,6 +40,7 @@ DIST_SUBDIRS = \
dummy \
eds \
key-file \
+ bluez \
telepathy \
libsocialweb \
tracker \
diff --git a/tests/bluez/Makefile.am b/tests/bluez/Makefile.am
new file mode 100644
index 00000000..46661fbf
--- /dev/null
+++ b/tests/bluez/Makefile.am
@@ -0,0 +1,48 @@
+include $(top_srcdir)/tests/test.mk
+
+AM_VALAFLAGS = \
+ $(test_valaflags) \
+ --vapidir=$(top_srcdir)/tests/lib/bluez \
+ --pkg bluez-test \
+ --pkg folks-generics \
+ $(NULL)
+
+AM_CPPFLAGS = \
+ $(test_cppflags) \
+ -I$(top_srcdir)/tests/lib/bluez \
+ $(NULL)
+
+AM_CFLAGS = \
+ $(test_cflags) \
+ $(NULL)
+
+LDADD = \
+ $(AM_LDADD) \
+ $(test_ldadd) \
+ $(top_builddir)/tests/lib/bluez/libbluez-test.la \
+ $(NULL)
+
+# in order from least to most complex
+noinst_PROGRAMS = \
+ device-properties \
+ individual-retrieval \
+ vcard-parsing \
+ $(NULL)
+
+TESTS = $(noinst_PROGRAMS)
+
+device_properties_SOURCES = \
+ device-properties.vala \
+ $(NULL)
+
+individual_retrieval_SOURCES = \
+ individual-retrieval.vala \
+ $(NULL)
+
+vcard_parsing_SOURCES = \
+ vcard-parsing.vala \
+ $(NULL)
+
+-include $(top_srcdir)/git.mk
+-include $(top_srcdir)/valgrind.mk
+-include $(top_srcdir)/check.mk
diff --git a/tests/bluez/device-properties.vala b/tests/bluez/device-properties.vala
new file mode 100644
index 00000000..19d806a5
--- /dev/null
+++ b/tests/bluez/device-properties.vala
@@ -0,0 +1,305 @@
+/*
+ * Copyright (C) 2013 Collabora Ltd.
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Philip Withnall <philip.withnall@collabora.co.uk>
+ */
+
+using Gee;
+using Folks;
+using BluezTest;
+
+public class DevicePropertiesTests : BluezTest.TestCase
+{
+ public DevicePropertiesTests ()
+ {
+ base ("DeviceProperties");
+
+ this.add_test ("device pairing", this.test_device_pairing);
+ this.add_test ("blocked device", this.test_blocked_device);
+ this.add_test ("device alias", this.test_device_alias);
+ }
+
+ /* Start with an unpaired Bluetooth device, and check that it’s not turned
+ * into a PersonaStore. Then pair the device, and check that it is added as
+ * a store. */
+ public void test_device_pairing ()
+ {
+ var main_loop = new GLib.MainLoop (null, false);
+
+ /* Set up a simple unpaired device. */
+ try
+ {
+ this.bluez_backend.mock_bluez.add_adapter ("hci0", "Test System");
+ this.bluez_backend.mock_bluez.add_device ("hci0",
+ this.bluez_backend.primary_device_address, "My Phone");
+ }
+ catch (IOError e1)
+ {
+ error ("Error setting up mock BlueZ device: %s", e1.message);
+ }
+
+ /* Set up its vCard in preparation. */
+ this.bluez_backend.set_simple_device_vcard (
+ "BEGIN:VCARD\n" +
+ "VERSION:3.0\n" +
+ "N:Jones;Pam;Mrs.\n" +
+ "FN:Pam Jones\n" +
+ "TEL:0123456789\n" +
+ "END:VCARD\n");
+
+ /* Set up the aggregator and wait until either quiescence, or the test
+ * times out and fails. Unset the primary store to prevent a warning. */
+ Environment.set_variable ("FOLKS_PRIMARY_STORE", "", true);
+
+ var aggregator = IndividualAggregator.dup ();
+ TestUtils.aggregator_prepare_and_wait_for_quiescence.begin (aggregator,
+ (o, r) =>
+ {
+ try
+ {
+ TestUtils.aggregator_prepare_and_wait_for_quiescence.end (r);
+ }
+ catch (GLib.Error e2)
+ {
+ error ("Error preparing aggregator: %s", e2.message);
+ }
+
+ main_loop.quit ();
+ });
+
+ TestUtils.loop_run_with_timeout (main_loop);
+
+ var real_backend =
+ aggregator.backend_store.dup_backend_by_name ("bluez");
+
+ /* Check there are no individuals and no persona stores. */
+ assert (aggregator.individuals.size == 0);
+ assert (real_backend.persona_stores.size == 0);
+
+ /* Wait for a signal about an added persona store. */
+ TestUtils.aggregator_wait_for_individuals.begin (aggregator,
+ {"Pam Jones"}, {}, (o, r) =>
+ {
+ TestUtils.aggregator_wait_for_individuals.end (r);
+ main_loop.quit ();
+ });
+
+ /* Pair the device. */
+ try
+ {
+ this.bluez_backend.mock_bluez.pair_device ("hci0",
+ this.bluez_backend.primary_device_address);
+ }
+ catch (IOError e4)
+ {
+ error ("Error pairing mock BlueZ device: %s", e4.message);
+ }
+
+ TestUtils.loop_run_with_timeout (main_loop);
+ }
+
+ /* Start with a blocked Bluetooth device, and check it’s not made into a
+ * PersonaStore. Then unblock the device and check a PersonaStore is created.
+ * Then block the device again and check the PersonaStore is removed. */
+ public void test_blocked_device ()
+ {
+ var main_loop = new GLib.MainLoop (null, false);
+
+ /* Set up a simple paired but blocked device. */
+ this.bluez_backend.create_simple_device_with_vcard (
+ "BEGIN:VCARD\n" +
+ "VERSION:3.0\n" +
+ "N:Jones;Pam;Mrs.\n" +
+ "FN:Pam Jones\n" +
+ "TEL:0123456789\n" +
+ "END:VCARD\n");
+
+ try
+ {
+ this.bluez_backend.mock_bluez.block_device ("hci0",
+ this.bluez_backend.primary_device_address);
+ }
+ catch (IOError e1)
+ {
+ error ("Error blocking device: %s", e1.message);
+ }
+
+ /* Set up the aggregator and wait until either quiescence, or the test
+ * times out and fails. Unset the primary store to prevent a warning. */
+ Environment.set_variable ("FOLKS_PRIMARY_STORE", "", true);
+
+ var aggregator = IndividualAggregator.dup ();
+ TestUtils.aggregator_prepare_and_wait_for_quiescence.begin (aggregator,
+ (o, r) =>
+ {
+ try
+ {
+ TestUtils.aggregator_prepare_and_wait_for_quiescence.end (r);
+ }
+ catch (GLib.Error e2)
+ {
+ error ("Error preparing aggregator: %s", e2.message);
+ }
+
+ main_loop.quit ();
+ });
+
+ TestUtils.loop_run_with_timeout (main_loop);
+
+ var real_backend =
+ aggregator.backend_store.dup_backend_by_name ("bluez");
+
+ /* Check there are no individuals and no persona stores. */
+ assert (aggregator.individuals.size == 0);
+ assert (real_backend.persona_stores.size == 0);
+
+ /* Wait for a signal about an added persona store. */
+ TestUtils.aggregator_wait_for_individuals.begin (aggregator,
+ {"Pam Jones"}, {}, (o, r) =>
+ {
+ TestUtils.aggregator_wait_for_individuals.end (r);
+ main_loop.quit ();
+ });
+
+ /* Unblock the device. */
+ try
+ {
+ this.bluez_backend.mock_bluez.pair_device ("hci0",
+ this.bluez_backend.primary_device_address);
+ }
+ catch (IOError e4)
+ {
+ error ("Error blocking device: %s", e4.message);
+ }
+
+ TestUtils.loop_run_with_timeout (main_loop);
+
+ /* Wait for a signal about a removed persona store. */
+ TestUtils.aggregator_wait_for_individuals.begin (aggregator,
+ {}, {"Pam Jones"}, (o, r) =>
+ {
+ TestUtils.aggregator_wait_for_individuals.end (r);
+ main_loop.quit ();
+ });
+
+ /* Block the device again. */
+ try
+ {
+ this.bluez_backend.mock_bluez.block_device ("hci0",
+ this.bluez_backend.primary_device_address);
+ }
+ catch (IOError e5)
+ {
+ error ("Error blocking device again: %s", e5.message);
+ }
+
+ TestUtils.loop_run_with_timeout (main_loop);
+
+ /* Check there are no individuals and no persona stores. */
+ assert (aggregator.individuals.size == 0);
+ assert (real_backend.persona_stores.size == 0);
+ }
+
+ /* Test that changes of a device’s Alias property result in the PersonaStore’s
+ * display-name being updated. */
+ public void test_device_alias ()
+ {
+ /* Set up the backend. */
+ string device_path = "";
+ this.bluez_backend.create_simple_device_with_vcard (
+ "BEGIN:VCARD\n" +
+ "VERSION:3.0\n" +
+ "N:Jones;Pam;Mrs.\n" +
+ "FN:Pam Jones\n" +
+ "TEL:0123456789\n" +
+ "END:VCARD\n",
+ null, out device_path);
+
+ var aggregator = IndividualAggregator.dup ();
+ TestUtils.aggregator_prepare_and_wait_for_individuals_sync_with_timeout (
+ aggregator, {"Pam Jones"});
+
+ /* Check the PersonaStore’s alias. */
+ var real_backend =
+ aggregator.backend_store.dup_backend_by_name ("bluez");
+ assert (real_backend.persona_stores.size == 1);
+
+ var real_store =
+ real_backend.persona_stores.get (
+ this.bluez_backend.primary_device_address);
+
+ /* FIXME: Have to get the display-name this way because
+ * Folks.PersonaStore.display_name is not declared as abstract. */
+ string display_name = "";
+ real_store.get ("display-name", out display_name);
+ assert (display_name == "My Phone");
+
+ /* Change the device’s Alias and see if the display-name changes. */
+ var main_loop = new GLib.MainLoop (null, false);
+ real_store.notify["display-name"].connect ((p) =>
+ {
+ real_store.get ("display-name", out display_name);
+ assert (display_name == "New Alias!");
+ main_loop.quit ();
+ });
+
+ try
+ {
+ Device mock_device =
+ Bus.get_proxy_sync (BusType.SYSTEM, "org.bluez", device_path);
+ org.freedesktop.DBus.Mock mock =
+ Bus.get_proxy_sync (BusType.SYSTEM, "org.bluez", device_path);
+
+ var props = new HashTable<string, Variant> (str_hash, str_equal);
+ props.insert ("Alias", "New Alias!");
+
+ mock_device.alias = "New Alias!";
+ mock.emit_signal ("org.freedesktop.DBus.Properties",
+ "PropertiesChanged", "sa{sv}as",
+ {
+ "org.bluez.Device1",
+ props,
+ new Variant.array (VariantType.STRING, {})
+ });
+ }
+ catch (IOError e1)
+ {
+ error ("Error setting device alias: %s", e1.message);
+ }
+
+ TestUtils.loop_run_with_timeout (main_loop);
+ }
+}
+
+/* Mini-copy of the org-bluez.vala file in the BlueZ backend. */
+[DBus (name = "org.bluez.Device1")]
+public interface Device : Object
+ {
+ [DBus (name = "Alias")]
+ public abstract string alias { owned get; set; }
+ }
+
+public int main (string[] args)
+{
+ Test.init (ref args);
+
+ var tests = new DevicePropertiesTests ();
+ tests.register ();
+ Test.run ();
+ tests.final_tear_down ();
+
+ return 0;
+}
diff --git a/tests/bluez/individual-retrieval.vala b/tests/bluez/individual-retrieval.vala
new file mode 100644
index 00000000..033821ed
--- /dev/null
+++ b/tests/bluez/individual-retrieval.vala
@@ -0,0 +1,232 @@
+/*
+ * Copyright (C) 2013 Collabora Ltd.
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Philip Withnall <philip.withnall@collabora.co.uk>
+ */
+
+using Gee;
+using Folks;
+using BluezTest;
+
+public class IndividualRetrievalTests : BluezTest.TestCase
+{
+ public IndividualRetrievalTests ()
+ {
+ base ("IndividualRetrieval");
+
+ this.add_test ("singleton individuals", this.test_singleton_individuals);
+ this.add_test ("empty address book", this.test_empty_address_book);
+ this.add_test ("photos downloaded later",
+ this.test_photos_downloaded_later);
+ }
+
+ /* Test that personas on a pre-existing Bluetooth device are successfully
+ * downloaded and presented as singleton individuals by the aggregator. */
+ public void test_singleton_individuals ()
+ {
+ var main_loop = new GLib.MainLoop (null, false);
+
+ /* Set up the backend. */
+ this.bluez_backend.create_simple_device_with_vcard (
+ "BEGIN:VCARD\n" +
+ "VERSION:3.0\n" +
+ "N:Gump;Forrest;Mr.\n" +
+ "FN:Forrest Gump\n" +
+ "NICKNAME:Fir\n" +
+ "TEL;TYPE=WORK,VOICE:(111) 555-1212\n" +
+ "TEL;TYPE=HOME,VOICE:(404) 555-1212\n" +
+ "EMAIL;TYPE=PREF,INTERNET:forrestgump@example.com\n" +
+ "URL;TYPE=HOME:http://example.com/\n" +
+ "END:VCARD\n" +
+ "\n" +
+ "BEGIN:VCARD\n" +
+ "VERSION:3.0\n" +
+ "N:Jones;Pam;Mrs.\n" +
+ "FN:Pam Jones\n" +
+ "TEL:0123456789\n" +
+ "END:VCARD\n");
+
+ /* Set up the aggregator and wait until either the expected persona are
+ * seen, or the test times out and fails. */
+ var aggregator = IndividualAggregator.dup ();
+ TestUtils.aggregator_prepare_and_wait_for_individuals.begin (aggregator,
+ {"Forrest Gump", "Pam Jones"}, (o, r) =>
+ {
+ try
+ {
+ TestUtils.aggregator_prepare_and_wait_for_individuals.end (r);
+ }
+ catch (GLib.Error e1)
+ {
+ error ("Error preparing aggregator: %s", e1.message);
+ }
+
+ main_loop.quit ();
+ });
+
+ TestUtils.loop_run_with_timeout (main_loop);
+ }
+
+ /* Test that an empty address book is handled correctly. */
+ public void test_empty_address_book ()
+ {
+ var main_loop = new GLib.MainLoop (null, false);
+
+ /* Set up the backend with *no* contacts. */
+ this.bluez_backend.create_simple_device_with_vcard ("");
+
+ /* Set up the aggregator and wait until either quiescence, or the test
+ * times out and fails. */
+ var aggregator = IndividualAggregator.dup ();
+ TestUtils.aggregator_prepare_and_wait_for_quiescence.begin (aggregator,
+ (o, r) =>
+ {
+ try
+ {
+ TestUtils.aggregator_prepare_and_wait_for_quiescence.end (r);
+ }
+ catch (GLib.Error e1)
+ {
+ error ("Error preparing aggregator: %s", e1.message);
+ }
+
+ main_loop.quit ();
+ });
+
+ TestUtils.loop_run_with_timeout (main_loop);
+
+ /* Check there are no individuals. */
+ assert (aggregator.individuals.size == 0);
+ }
+
+ /* Test that photos are downloaded in a second sweep of the address book. */
+ public void test_photos_downloaded_later ()
+ {
+ var main_loop = new GLib.MainLoop (null, false);
+
+ /* Set up the backend, at first with a vCard without a photo. */
+ var vcard_signal_id = this.bluez_backend.create_simple_device_with_vcard (
+ "BEGIN:VCARD\n" +
+ "VERSION:3.0\n" +
+ "N:Gump;Forrest;Mr.\n" +
+ "FN:Forrest Gump\n" +
+ "NICKNAME:Fir\n" +
+ "TEL;TYPE=WORK,VOICE:(111) 555-1212\n" +
+ "TEL;TYPE=HOME,VOICE:(404) 555-1212\n" +
+ "EMAIL;TYPE=PREF,INTERNET:forrestgump@example.com\n" +
+ "URL;TYPE=HOME:http://example.com/\n" +
+ "END:VCARD\n");
+
+ /* Set up the aggregator and wait until either the expected persona are
+ * seen, or the test times out and fails. */
+ var aggregator = IndividualAggregator.dup ();
+ TestUtils.aggregator_prepare_and_wait_for_individuals.begin (aggregator,
+ {"Forrest Gump"}, (o, r) =>
+ {
+ try
+ {
+ TestUtils.aggregator_prepare_and_wait_for_individuals.end (r);
+ }
+ catch (GLib.Error e1)
+ {
+ error ("Error preparing aggregator: %s", e1.message);
+ }
+
+ main_loop.quit ();
+ });
+
+ TestUtils.loop_run_with_timeout (main_loop);
+
+ /* Re-set the backend to now return a vCard with a photo (and nothing
+ * else). */
+ this.bluez_backend.mock_obex.disconnect (vcard_signal_id);
+ this.bluez_backend.set_simple_device_vcard (
+ "BEGIN:VCARD\n" +
+ "VERSION:3.0\n" +
+ "N:Gump;Forrest;Mr.\n" +
+ "FN:Forrest Gump\n" +
+ "NICKNAME:Fir\n" +
+ "TEL;TYPE=WORK,VOICE:(111) 555-1212\n" +
+ "TEL;TYPE=HOME,VOICE:(404) 555-1212\n" +
+ "EMAIL;TYPE=PREF,INTERNET:forrestgump@example.com\n" +
+ "URL;TYPE=HOME:http://example.com/\n" +
+ "PHOTO;TYPE=jpeg;ENCODING=b:" +
+ "/9j/4AAQSkZJRgABAQEASABIAAD/2wBDAAMCAgMCAgMDAwMEAwMEBQgFBQQEBQoHBwYIDAoMDAsK" +
+ "CwsNDhIQDQ4RDgsLEBYQERMUFRUVDA8XGBYUGBIUFRT/2wBDAQMEBAUEBQkFBQkUDQsNFBQUFBQU" +
+ "FBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBT/wgARCAAlACADAREA" +
+ "AhEBAxEB/8QAGgAAAwADAQAAAAAAAAAAAAAABgcIAAMFBP/EABoBAQADAQEBAAAAAAAAAAAAAAAD" +
+ "BAUCBgf/2gAMAwEAAhADEAAAAapJXNBV5gl8G4uLkNUaUIYew4otQ8+a+gYntscQryguHbZ+pAH2" +
+ "Y+ZPwzoOv//EAB4QAAICAwADAQAAAAAAAAAAAAMFBAYBAgcAEBUW/9oACAEBAAEFAvOtT230ufOW" +
+ "qmzepo/tWKyw96ZYgHHKBdX352vVdJrXkd/UBaVXjDrY8F/kTvyDKxMj26aPMTn6QdZJLrwz5FUc" +
+ "sSyqFDTbKlmkQP8A/8QAHxEAAQQCAwEBAAAAAAAAAAAAAgABAwQREhMgITFR/9oACAEDAQE/Aeta" +
+ "UInfdlMYmWRbHavTBh2L3KnieE9VUjGWTUvxS0dI8i+XUd6UGx9Vmxz48VabhPbCntHM+PjL/8QA" +
+ "JxEAAQMDAQcFAAAAAAAAAAAAAQIDBAAFETESICFBUXHwBhMikfH/2gAIAQIBAT8B3bvBenNpSyvG" +
+ "OXWoEZyKwG3V7R84b12vj5dLLPw2T9480q2zkz44dGvPvV4kriRg82dCPyonqISJYQ4NlB4DvUiw" +
+ "w5CiviCatltRb0qCTnNXGGmcx7SjioFpjQRlIyrr5pX/xAAuEAACAQIEAwYGAwAAAAAAAAABAgMA" +
+ "BAUREhMhIjFBUWFxgZEQFDJCUrFD0eH/2gAIAQEABj8CpYbS4eG0gt1ldYpNJJZyufeezy9aiwbE" +
+ "ZTNHcxtlnNuaWGfbmfxIy+N7dWsC3UdqiWhYj+TnLZeWpQawXHJY12ASjpAv0nMlvcMx9KSaFxJF" +
+ "INSuvQirq5Vgtww24PFz0/v0q1sgdTqM5G73PE1iO4OaGIzofFRn/nrV5hkj57BEsQPYrdR7/uvl" +
+ "7m3jeGJzkG48emdK/wBw+oeNNhgmVZ7yN00fdoIIzqXel3p5+Xd09O4UzxTSQyE5/kPajLPid3Fo" +
+ "5QLJ9nPz6502JWtxcG6HBmuH3NQpXY7sx46yP1X/xAAfEAEAAQUBAAMBAAAAAAAAAAABEQAhQVFh" +
+ "MRBxkfD/2gAIAQEAAT8hrANf3gCCQckqMY2Pp+fB6xkNfMTQP0gjfHgXeU1IRQE+0Qm17o9OXZUS" +
+ "I0EKhlJs4GYvDql0TMdx/Zrqhsh1ptBl1SIe6wi4XVeEI3eM/RZfP2hzBYDFFZsCjIkcF/d1Z4w1" +
+ "CA9H+NUlhU7Su1f8Sr7hPO0xWEeRf2s7OFfF4ZkLzu2iNllBjgxX/9oADAMBAAIAAwAAABASQViS" +
+ "BhbUn//EACARAQABAwQDAQAAAAAAAAAAAAERACExQVFhwSCBsfH/2gAIAQMBAT8Q8dUAs5T9pPCf" +
+ "efIvfgyWJ75p28aO5SorS9O9T8Qu6W4KFOAWxp6plOEd0kaUkUkTwHe9f//EACERAQACAQQDAAMA" +
+ "AAAAAAAAAAERMSEAQVGBIGFxkbHR/9oACAECAQE/EPHLEpZIfSZxxXemy3S7YMFyht+ivKWOXKMs" +
+ "kE4rsO86wPVHAvps9OocDLrJOe351EQMF5pCsTDXBbyOoSVR3d4Z0yuUmcVPv3pxASM3U/OdCC88" +
+ "z1/F7uv/xAAdEAEBAAMBAQEBAQAAAAAAAAABEQAhMUFRcWGB/9oACAEBAAE/EPcBt9CLg0mkItkW" +
+ "bCK+/Mi2KFKVLnuC5jcdY7QomwK5LuBR8HYKQcR1QYytJ8M0iIji8CRilWERrGzK/cZHYHeFgPgW" +
+ "tVgRTHHylCBCwOKZYo4K7QfGQ+v/AA6JyUCdhZB0LSgxVErXI33xGn7/ABwIkQz6W1i5pB7l1O1Q" +
+ "UdgKta18AhSHHRqw0Vdfqyk3ggOrmCAjpsQ7XOmIVMFktoFUcCCccJdlLIMWq/ZA/9k=\n" +
+ "END:VCARD\n");
+
+ /* The individual should not have a photo to begin with; wait until one
+ * appears. */
+ assert (aggregator.individuals.size == 1);
+ var iter = aggregator.individuals.map_iterator ();
+ while (iter.next () == true)
+ {
+ var individual = iter.get_value ();
+ assert (individual.avatar == null);
+
+ /* Wait for it to change. Assert that only the avatar changes. */
+ individual.notify.connect ((pspec) =>
+ {
+ assert (pspec.name == "avatar");
+ assert (individual.avatar != null);
+ main_loop.quit ();
+ });
+ }
+
+ /* There’s normally a 5s wait between poll attempts in the backend, but
+ * we set the FOLKS_BLUEZ_TIMEOUT_DIVISOR in the TestCase to reduce
+ * this. */
+ TestUtils.loop_run_with_timeout (main_loop);
+ }
+}
+
+public int main (string[] args)
+{
+ Test.init (ref args);
+
+ var tests = new IndividualRetrievalTests ();
+ tests.register ();
+ Test.run ();
+ tests.final_tear_down ();
+
+ return 0;
+}
diff --git a/tests/bluez/vcard-parsing.vala b/tests/bluez/vcard-parsing.vala
new file mode 100644
index 00000000..f9e91002
--- /dev/null
+++ b/tests/bluez/vcard-parsing.vala
@@ -0,0 +1,255 @@
+/*
+ * Copyright (C) 2013 Collabora Ltd.
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Philip Withnall <philip.withnall@collabora.co.uk>
+ */
+
+using Gee;
+using Folks;
+using BluezTest;
+
+public class VcardParsingTests : BluezTest.TestCase
+{
+ public VcardParsingTests ()
+ {
+ base ("VcardParsing");
+
+ this.add_test ("multiple attributes", this.test_multiple_attributes);
+ this.add_test ("name components", this.test_name_components);
+ this.add_test ("encoding", this.test_encoding);
+ }
+
+ /* Test that vCards containing multiple attributes with the same name (e.g.
+ * multiple phone numbers or e-mail addresses) are parsed correctly. */
+ public void test_multiple_attributes ()
+ {
+ /* Set up the backend. */
+ this.bluez_backend.create_simple_device_with_vcard (
+ "BEGIN:VCARD\n" +
+ "VERSION:3.0\n" +
+ "FN:Forrest Gump\n" +
+ "TEL;TYPE=WORK,VOICE:(111) 555-1212\n" +
+ "TEL;TYPE=HOME,VOICE:(404) 555-1212\n" +
+ "EMAIL;TYPE=PREF,INTERNET:forrestgump@example.com\n" +
+ "EMAIL:test@example.com\n" +
+ "URL;TYPE=HOME:http://example.com/\n" +
+ "URL:http://forest.com/\n" +
+ "URL:https://test.com/\n" +
+ "END:VCARD\n");
+
+ /* Set up the aggregator and wait until either the expected persona are
+ * seen, or the test times out and fails. */
+ var aggregator = IndividualAggregator.dup ();
+ TestUtils.aggregator_prepare_and_wait_for_individuals_sync_with_timeout (
+ aggregator, {"Forrest Gump"});
+
+ /* Check the properties of our friend Forrest. */
+ var ind = TestUtils.get_individual_by_name (aggregator, "Forrest Gump");
+
+ var expected_phone_numbers = new SmallSet<PhoneFieldDetails> (
+ AbstractFieldDetails<string>.hash_static,
+ AbstractFieldDetails<string>.equal_static);
+
+ var expected_phone_fd = new PhoneFieldDetails ("(111) 555-1212");
+ expected_phone_fd.add_parameter ("type", "work");
+ expected_phone_fd.add_parameter ("type", "voice");
+ expected_phone_numbers.add (expected_phone_fd);
+
+ expected_phone_fd = new PhoneFieldDetails ("(404) 555-1212");
+ expected_phone_fd.add_parameter ("type", "home");
+ expected_phone_fd.add_parameter ("type", "voice");
+ expected_phone_numbers.add (expected_phone_fd);
+
+ var expected_email_addresses = new SmallSet<EmailFieldDetails> (
+ AbstractFieldDetails<string>.hash_static,
+ AbstractFieldDetails<string>.equal_static);
+
+ var expected_email_fd = new EmailFieldDetails ("forrestgump@example.com");
+ expected_email_fd.add_parameter ("type", "pref");
+ expected_email_fd.add_parameter ("type", "internet");
+ expected_email_addresses.add (expected_email_fd);
+
+ expected_email_fd = new EmailFieldDetails ("test@example.com");
+ expected_email_addresses.add (expected_email_fd);
+
+ var expected_uris = new SmallSet<UrlFieldDetails> (
+ AbstractFieldDetails<string>.hash_static,
+ AbstractFieldDetails<string>.equal_static);
+
+ var expected_uri_fd = new UrlFieldDetails ("http://example.com/");
+ expected_uri_fd.add_parameter ("type", "home");
+ expected_uris.add (expected_uri_fd);
+
+ expected_uri_fd = new UrlFieldDetails ("http://forest.com/");
+ expected_uris.add (expected_uri_fd);
+
+ expected_uri_fd = new UrlFieldDetails ("https://test.com/");
+ expected_uris.add (expected_uri_fd);
+
+ assert (Utils.set_afd_equal (ind.phone_numbers, expected_phone_numbers));
+ assert (Utils.set_afd_equal (ind.email_addresses,
+ expected_email_addresses));
+ assert (Utils.set_afd_equal (ind.urls, expected_uris));
+ }
+
+ /* Test that vCards with different numbers of values for their N (structured
+ * name) attribute are parsed correctly. */
+ public void test_name_components ()
+ {
+ /* Set up the backend. */
+ this.bluez_backend.create_simple_device_with_vcard (
+ /* Valid N attributes. */
+ "BEGIN:VCARD\n" +
+ "VERSION:3.0\n" +
+ "FN:John Public\n" +
+ "N:Public;John;Quinlan;Mr.;Esq.\n" +
+ "END:VCARD\n" +
+ "\n" +
+ "BEGIN:VCARD\n" +
+ "VERSION:3.0\n" +
+ "FN:John Stevenson\n" +
+ "N:Stevenson;John;Philip,Paul;Dr.;Jr.,M.D.,A.C.P.\n" +
+ "END:VCARD\n" +
+ "\n" +
+ "BEGIN:VCARD\n" +
+ "VERSION:3.0\n" +
+ "FN:Franco Dianno\n" +
+ "N:Dianno;Franco;;;\n" +
+ "END:VCARD\n" +
+ "\n" +
+ /* Invalid N attributes (but we should handle them anyway). */
+ "BEGIN:VCARD\n" +
+ "VERSION:3.0\n" +
+ "FN:Amelia Smith\n" +
+ "N:Smith;Amelia;David;Dr.\n" +
+ "END:VCARD\n" +
+ "\n" +
+ "BEGIN:VCARD\n" +
+ "VERSION:3.0\n" +
+ "FN:Sadie Jones\n" +
+ "N:Jones;Sadie;M.\n" +
+ "END:VCARD\n" +
+ "\n" +
+ "BEGIN:VCARD\n" +
+ "VERSION:3.0\n" +
+ "FN:Alex Lawson\n" +
+ "N:Lawson;Alex\n" +
+ "END:VCARD\n");
+
+ /* Set up the aggregator and wait until either the expected persona are
+ * seen, or the test times out and fails. */
+ var aggregator = IndividualAggregator.dup ();
+ TestUtils.aggregator_prepare_and_wait_for_individuals_sync_with_timeout (
+ aggregator,
+ {
+ "John Public",
+ "John Stevenson",
+ "Franco Dianno",
+ "Amelia Smith",
+ "Sadie Jones",
+ "Alex Lawson"
+ });
+
+ /* Check the properties of our individuals. */
+ var ind = TestUtils.get_individual_by_name (aggregator, "John Public");
+ var expected_name =
+ new StructuredName ("Public", "John", "Quinlan", "Mr.", "Esq.");
+ assert (ind.structured_name.equal (expected_name));
+
+ ind = TestUtils.get_individual_by_name (aggregator, "John Stevenson");
+ expected_name =
+ new StructuredName ("Stevenson", "John", "Philip,Paul", "Dr.",
+ "Jr.,M.D.,A.C.P.");
+ assert (ind.structured_name.equal (expected_name));
+
+ ind = TestUtils.get_individual_by_name (aggregator, "Franco Dianno");
+ expected_name = new StructuredName ("Dianno", "Franco", null, null, null);
+ assert (ind.structured_name.equal (expected_name));
+
+ ind = TestUtils.get_individual_by_name (aggregator, "Amelia Smith");
+ expected_name =
+ new StructuredName ("Smith", "Amelia", "David", "Dr.", null);
+ assert (ind.structured_name.equal (expected_name));
+
+ ind = TestUtils.get_individual_by_name (aggregator, "Sadie Jones");
+ expected_name = new StructuredName ("Jones", "Sadie", "M.", null, null);
+ assert (ind.structured_name.equal (expected_name));
+
+ ind = TestUtils.get_individual_by_name (aggregator, "Alex Lawson");
+ expected_name = new StructuredName ("Lawson", "Alex", null, null, null);
+ assert (ind.structured_name.equal (expected_name));
+ }
+
+ /* Test that vCards with weird encodings are parsed correctly. */
+ public void test_encoding ()
+ {
+ /* Set up the backend. */
+ this.bluez_backend.create_simple_device_with_vcard (
+ /* From https://bugs.kde.org/show_bug.cgi?id=98790 */
+ "BEGIN:VCARD\n" +
+ "VERSION:2.1\n" +
+ "FN:Test 1\n" +
+ "N;CHARSET=UTF-8:溌剌;元気\n" +
+ "END:VCARD\n" +
+ "\n" +
+ /* From https://git.gnome.org/browse/evolution-data-server/tree/tests/
+ * libebook-contacts/test-vcard-parsing.c#n360 */
+ "BEGIN:VCARD\n" +
+ "VERSION:2.1\n" +
+ "FN;ENCODING=quoted-printable:ActualValue=20=C4=9B=C5=A1" +
+ "=C4=8D=C5=99=C5=BE=C3=BD=C3=A1=C3=AD=C3=A9=C3=BA=C5=AF=C3" +
+ "=B3=C3=B6=C4=9A=C5=A0=C4=8C=C5=98=C5=BD=C3=9D=C3=81=C3=8D" +
+ "=C3=89=C3=9A=C5=AE=C3=93=C3=96=C2=A7=201234567890=2012345" +
+ "67890=201234567890=201234567890=201234567890\n" +
+ "END:VCARD\n");
+
+ /* Set up the aggregator and wait until either the expected persona are
+ * seen, or the test times out and fails. */
+ var aggregator = IndividualAggregator.dup ();
+ TestUtils.aggregator_prepare_and_wait_for_individuals_sync_with_timeout (
+ aggregator,
+ {
+ "Test 1",
+ "ActualValue ěščřžýáíéúůóöĚŠČŘŽÝÁÍÉÚŮÓÖ§ " +
+ "1234567890 1234567890 1234567890 1234567890 1234567890"
+ });
+
+ /* Check the properties of our individuals. */
+ var ind = TestUtils.get_individual_by_name (aggregator, "Test 1");
+ var expected_name =
+ new StructuredName ("溌剌", "元気", null, null, null);
+ assert (ind.structured_name.equal (expected_name));
+
+ ind =
+ TestUtils.get_individual_by_name (aggregator,
+ "ActualValue ěščřžýáíéúůóöĚŠČŘŽÝÁÍÉÚŮÓÖ§ " +
+ "1234567890 1234567890 1234567890 1234567890 1234567890");
+ assert (ind.full_name == "ActualValue ěščřžýáíéúůóöĚŠČŘŽÝÁÍÉÚŮÓÖ§ " +
+ "1234567890 1234567890 1234567890 1234567890 1234567890");
+ }
+}
+
+public int main (string[] args)
+{
+ Test.init (ref args);
+
+ var tests = new VcardParsingTests ();
+ tests.register ();
+ Test.run ();
+ tests.final_tear_down ();
+
+ return 0;
+}
diff --git a/tests/dummy/Makefile.am b/tests/dummy/Makefile.am
index 90fd2d58..668dbe16 100644
--- a/tests/dummy/Makefile.am
+++ b/tests/dummy/Makefile.am
@@ -24,6 +24,7 @@ LDADD = \
TESTS = \
individual-retrieval \
add-persona \
+ linkable-properties \
$(NULL)
noinst_PROGRAMS = $(TESTS)
@@ -36,6 +37,10 @@ add_persona_SOURCES = \
add-persona.vala \
$(NULL)
+linkable_properties_SOURCES = \
+ linkable-properties.vala \
+ $(NULL)
+
-include $(top_srcdir)/git.mk
-include $(top_srcdir)/valgrind.mk
-include $(top_srcdir)/check.mk
diff --git a/tests/dummy/linkable-properties.vala b/tests/dummy/linkable-properties.vala
new file mode 100644
index 00000000..716feb56
--- /dev/null
+++ b/tests/dummy/linkable-properties.vala
@@ -0,0 +1,275 @@
+/*
+ * Copyright (C) 2014 Renato Araujo Oliveira Filho
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Raul Gutierrez Segales <raul.gutierrez.segales@collabora.co.uk>
+ * Travis Reitter <travis.reitter@collabora.co.uk>
+ * Renato Araujo Oliveira Filho <renato@canonical.com>
+ *
+ */
+
+using Folks;
+using Gee;
+
+public class LinkablePropertiesTests : DummyTest.TestCase
+{
+ private IndividualAggregator _aggregator;
+ private GLib.MainLoop _main_loop;
+ private bool _found_before_update;
+ private bool _found_after_update;
+
+ /* NOTE: each full name must remain unique. Likewise for email. */
+ private const string _full_name_1 = "bernie h. innocenti";
+ private const string _email_1 = "bernie@example.org";
+ private const string _phone_1 = "5551234";
+ private const string _full_name_2 = "Clyde McPoyle";
+ private const string _email_2 = "clyde@example.org";
+ private const string _phone_2 = "987654321";
+ private Individual _ind_1;
+ private Individual _ind_2;
+
+ /* In general, these tests are meant to check basic behavior so we don't need
+ * to sprinkle that throughout (and potentially revise) within unrelated tests
+ */
+ public LinkablePropertiesTests ()
+ {
+ base ("LinkableProperties");
+
+ this.add_test ("correct aggregation after linkable property change",
+ this.test_linkable_properties_aggregate_after_change);
+ }
+
+ public override void set_up ()
+ {
+ base.set_up ();
+
+ this._found_before_update = false;
+ this._found_after_update = false;
+ }
+
+ public override void configure_primary_store ()
+ {
+ base.configure_primary_store ();
+ this.dummy_persona_store.update_trust_level (PersonaStoreTrust.FULL);
+ }
+
+ private async void _add_persona (owned Gee.HashMap<string, Value?> c)
+ {
+ HashTable<string, Value?> details = new HashTable<string, Value?>
+ (str_hash, str_equal);
+
+ Value? v1 = Value (typeof (string));
+ v1.set_string (c["full_name"].get_string());
+ details.insert (Folks.PersonaStore.detail_key (PersonaDetail.FULL_NAME),
+ (owned) v1);
+
+ Value? v2 = Value (typeof (Set));
+ var emails = new HashSet<EmailFieldDetails> (
+ AbstractFieldDetails<string>.hash_static,
+ AbstractFieldDetails<string>.equal_static);
+ var email_1 = new EmailFieldDetails (c["email_1"].get_string());
+ email_1.set_parameter (AbstractFieldDetails.PARAM_TYPE,
+ AbstractFieldDetails.PARAM_TYPE_HOME);
+ emails.add (email_1);
+ v2.set_object (emails);
+ details.insert (
+ Folks.PersonaStore.detail_key (PersonaDetail.EMAIL_ADDRESSES),
+ (owned) v2);
+
+ Value? v5 = Value (typeof (Set));
+ var phones = new HashSet<PhoneFieldDetails> (
+ AbstractFieldDetails<string>.hash_static,
+ AbstractFieldDetails<string>.equal_static);
+
+ var phone_1 = new PhoneFieldDetails (c["home_phone"].get_string());
+ phone_1.set_parameter (AbstractFieldDetails.PARAM_TYPE,
+ AbstractFieldDetails.PARAM_TYPE_HOME);
+ phones.add (phone_1);
+ v5.set_object (phones);
+ details.insert (
+ Folks.PersonaStore.detail_key (PersonaDetail.PHONE_NUMBERS),
+ (owned) v5);
+
+ try
+ {
+ yield this._aggregator.add_persona_from_details (null,
+ this.dummy_persona_store, details);
+ }
+ catch (Folks.IndividualAggregatorError e)
+ {
+ GLib.warning ("[AddPersonaError] add_persona_from_details: %s\n",
+ e.message);
+ }
+ }
+
+
+ /* Check that two unaggregated Personas get aggregated after one changes its
+ * linkable property to match the other's (ie, they get linked)
+ */
+ private async void _add_personas ()
+ {
+ Gee.HashMap<string, Value?> c;
+ Value? v;
+
+ this._found_before_update = false;
+ this._found_after_update = false;
+
+ c = new Gee.HashMap<string, Value?> ();
+ v = Value (typeof (string));
+ v.set_string (_full_name_1);
+ c.set ("full_name", (owned) v);
+ v = Value (typeof (string));
+ v.set_string (_email_1);
+ c.set ("email_1", (owned) v);
+ v = Value (typeof (string));
+ v.set_string (_phone_1);
+ c.set ("home_phone", (owned) v);
+ yield this._add_persona (c);
+
+ c = new Gee.HashMap<string, Value?> ();
+ v = Value (typeof (string));
+ v.set_string (_full_name_2);
+ c.set ("full_name", (owned) v);
+ v = Value (typeof (string));
+ v.set_string (_email_2);
+ c.set ("email_1", (owned) v);
+ v = Value (typeof (string));
+ v.set_string (_phone_2);
+ c.set ("home_phone", (owned) v);
+ yield this._add_persona (c);
+ }
+
+ private void test_linkable_properties_aggregate_after_change ()
+ {
+ this._main_loop = new GLib.MainLoop (null, false);
+ test_linkable_properties_aggregate_after_change_continue.begin ();
+ TestUtils.loop_run_with_timeout (this._main_loop);
+
+ assert (this._found_before_update);
+ assert (this._found_after_update);
+ }
+
+ private async void test_linkable_properties_aggregate_after_change_continue ()
+ {
+ this._aggregator = IndividualAggregator.dup ();
+ this._aggregator.individuals_changed_detailed.connect (this._individuals_changed_aggregate_after_change_cb);
+ try
+ {
+ yield this._aggregator.prepare ();
+ }
+ catch (GLib.Error e)
+ {
+ GLib.warning ("Error when calling prepare: %s\n", e.message);
+ }
+
+ yield this._add_personas ();
+ }
+
+ private void _individuals_changed_aggregate_after_change_cb (
+ MultiMap<Individual?, Individual?> changes)
+ {
+ var added = changes.get_values ();
+
+ if (!this._found_before_update)
+ {
+ foreach (Individual i in added)
+ {
+ assert (i != null);
+
+ var name = (Folks.NameDetails) i;
+
+ if (name.full_name == _full_name_1)
+ {
+ this._ind_1 = i;
+ }
+ /* Change the second Persona's email address to match the first so
+ * they should get aggregated */
+ else if (name.full_name == _full_name_2)
+ {
+ this._ind_2 = i;
+ this._found_before_update = true;
+
+ foreach (var p in i.personas)
+ {
+ var emails = new HashSet<EmailFieldDetails> (
+ AbstractFieldDetails<string>.hash_static,
+ AbstractFieldDetails<string>.equal_static);
+ var email_1 = new EmailFieldDetails (_email_1);
+ email_1.set_parameter (AbstractFieldDetails.PARAM_TYPE,
+ AbstractFieldDetails.PARAM_TYPE_OTHER);
+ emails.add (email_1);
+ ((EmailDetails) p).email_addresses = emails;
+ }
+ }
+ }
+ }
+ else
+ {
+ Individual replaced;
+
+ if (changes.contains (this._ind_1))
+ {
+ replaced = this._ind_1;
+ }
+ else if (changes.contains (this._ind_2))
+ {
+ replaced = this._ind_2;
+ }
+ else
+ {
+ return;
+ }
+
+ var replacements = changes.get (replaced);
+ foreach (var r in replacements)
+ {
+ var phone_fd_1 = new PhoneFieldDetails (_phone_1);
+ var phone_fd_2 = new PhoneFieldDetails (_phone_1);
+ var num_equal_1 = false;
+ var num_equal_2 = false;
+
+ if (r.personas.size == 2)
+ {
+ foreach (var num in r.phone_numbers)
+ {
+ if (num.values_equal (phone_fd_1))
+ num_equal_1 = true;
+
+ if (num.values_equal (phone_fd_2))
+ num_equal_2 = true;
+ }
+
+ if (num_equal_1 && num_equal_2)
+ {
+ this._found_after_update = true;
+ this._main_loop.quit ();
+ }
+ }
+ }
+ }
+ }
+}
+
+public int main (string[] args)
+{
+ Test.init (ref args);
+
+ var tests = new LinkablePropertiesTests ();
+ tests.register ();
+ Test.run ();
+ tests.final_tear_down ();
+
+ return 0;
+}
diff --git a/tests/eds/Makefile.am b/tests/eds/Makefile.am
index 687ebe62..29f7bb33 100644
--- a/tests/eds/Makefile.am
+++ b/tests/eds/Makefile.am
@@ -77,13 +77,6 @@ TESTS = \
perf \
$(NULL)
-RUN_WITH_PRIVATE_BUS = $(top_srcdir)/tests/tools/with-session-bus-eds.sh
-
-TESTS_ENVIRONMENT = \
- $(RUN_WITH_PRIVATE_BUS) \
- --session \
- --
-
noinst_PROGRAMS = \
$(TESTS) \
helper-create-many-contacts \
@@ -239,11 +232,6 @@ helper_prepare_aggregator_SOURCES = \
helper-prepare-aggregator.vala \
$(NULL)
-CLEANFILES = \
- *.pid \
- *.address \
- $(NULL)
-
-include $(top_srcdir)/git.mk
-include $(top_srcdir)/check.mk
-include $(top_srcdir)/valgrind.mk
diff --git a/tests/eds/helper-create-many-contacts.vala b/tests/eds/helper-create-many-contacts.vala
index 000348ff..bbeb1847 100644
--- a/tests/eds/helper-create-many-contacts.vala
+++ b/tests/eds/helper-create-many-contacts.vala
@@ -131,7 +131,7 @@ public class Main
{
Intl.setlocale (LocaleCategory.ALL, "");
- if (Environment.get_variable ("FOLKS_TESTS_SANDBOXED_DBUS") != "eds")
+ if (Environment.get_variable ("FOLKS_TESTS_SANDBOXED_DBUS") != "no-services")
error ("e-d-s helpers must be run in a private D-Bus session with " +
"e-d-s services");
diff --git a/tests/eds/helper-delete-contacts.vala b/tests/eds/helper-delete-contacts.vala
index 46d2e35c..816767da 100644
--- a/tests/eds/helper-delete-contacts.vala
+++ b/tests/eds/helper-delete-contacts.vala
@@ -55,7 +55,7 @@ public class Main
{
Intl.setlocale (LocaleCategory.ALL, "");
- if (Environment.get_variable ("FOLKS_TESTS_SANDBOXED_DBUS") != "eds")
+ if (Environment.get_variable ("FOLKS_TESTS_SANDBOXED_DBUS") != "no-services")
error ("e-d-s helpers must be run in a private D-Bus session with " +
"e-d-s services");
diff --git a/tests/eds/helper-prepare-aggregator.vala b/tests/eds/helper-prepare-aggregator.vala
index 1b71a6bb..50bd439f 100644
--- a/tests/eds/helper-prepare-aggregator.vala
+++ b/tests/eds/helper-prepare-aggregator.vala
@@ -62,7 +62,7 @@ public class Main
{
Intl.setlocale (LocaleCategory.ALL, "");
- if (Environment.get_variable ("FOLKS_TESTS_SANDBOXED_DBUS") != "eds" ||
+ if (Environment.get_variable ("FOLKS_TESTS_SANDBOXED_DBUS") != "no-services" ||
Environment.get_variable ("FOLKS_BACKENDS_ALLOWED") != "eds" ||
Environment.get_variable ("FOLKS_PRIMARY_STORE") == null)
error ("e-d-s helpers must be run in a private D-Bus session with " +
diff --git a/tests/folks/Makefile.am b/tests/folks/Makefile.am
index a04e8461..9fda5745 100644
--- a/tests/folks/Makefile.am
+++ b/tests/folks/Makefile.am
@@ -54,10 +54,6 @@ noinst_PROGRAMS = \
init \
$(NULL)
-TESTS_ENVIRONMENT = \
- $(top_srcdir)/tests/tools/execute-test.sh \
- $(NULL)
-
TESTS = $(noinst_PROGRAMS)
backend_loading_SOURCES = \
diff --git a/tests/lib/Makefile.am b/tests/lib/Makefile.am
index 49dde706..2442d405 100644
--- a/tests/lib/Makefile.am
+++ b/tests/lib/Makefile.am
@@ -5,6 +5,12 @@ SUBDIRS = \
key-file \
$(NULL)
+if ENABLE_BLUEZ
+if HAVE_BLUEZ_TESTS
+SUBDIRS += bluez
+endif
+endif
+
if ENABLE_TELEPATHY
# Build the contactlist first because autotools fails to recognize the
# dependencies implicitly. There may be a better way to fix this, but then I'd
@@ -30,6 +36,7 @@ endif
DIST_SUBDIRS = \
dummy \
key-file \
+ bluez \
telepathy \
eds \
libsocialweb \
@@ -41,9 +48,13 @@ noinst_LTLIBRARIES = libfolks-test.la
libfolks_test_la_SOURCES = \
disconnection-queue.vala \
haze-remove-directory.c \
+ gtestdbus.c \
+ gtestdbus.h \
+ folks-test-dbus.vapi \
test-case.vala \
test-case-helper.c \
test-utils.vala \
+ org-freedesktop-dbus-mock.vala \
$(NULL)
libfolks_test_la_CFLAGS = \
@@ -81,6 +92,7 @@ libfolks_test_la_VALAFLAGS = \
$(ERROR_VALAFLAGS) \
--vapidir=$(abs_top_srcdir)/folks \
--vapidir=$(abs_top_builddir)/folks \
+ --vapidir=$(abs_top_srcdir)/tests/lib \
--pkg gobject-2.0 \
--pkg gio-2.0 \
--pkg gee-0.8 \
diff --git a/tests/lib/bluez/Makefile.am b/tests/lib/bluez/Makefile.am
new file mode 100644
index 00000000..a2a382dd
--- /dev/null
+++ b/tests/lib/bluez/Makefile.am
@@ -0,0 +1,51 @@
+noinst_LTLIBRARIES = libbluez-test.la
+
+libbluez_test_la_VALAFLAGS = \
+ $(AM_VALAFLAGS) \
+ $(TARGET_VALAFLAGS) \
+ $(ERROR_VALAFLAGS) \
+ --library bluez-test \
+ --vapi bluez-test.vapi \
+ --header bluez-test.h \
+ --vapidir=$(abs_srcdir) \
+ --vapidir=$(abs_builddir) \
+ --vapidir=$(abs_top_srcdir)/folks \
+ --vapidir=$(abs_top_builddir)/folks \
+ --vapidir=$(abs_top_srcdir)/tests/lib \
+ --vapidir=$(abs_top_builddir)/tests/lib \
+ --pkg folks-test \
+ --pkg folks-test-dbus \
+ -g \
+ $(NULL)
+
+libbluez_test_la_SOURCES = \
+ backend.vala \
+ test-case.vala \
+ $(NULL)
+
+libbluez_test_la_CPPFLAGS = \
+ $(AM_CPPFLAGS) \
+ -include $(top_srcdir)/folks/warnings.h \
+ $(NULL)
+
+libbluez_test_la_CFLAGS = \
+ -I$(top_srcdir) \
+ -I$(top_srcdir)/tests/lib \
+ $(AM_CFLAGS) \
+ $(ERROR_CFLAGS) \
+ $(GLIB_CFLAGS) \
+ $(GEE_CFLAGS) \
+ $(NULL)
+
+libbluez_test_la_LIBADD = \
+ $(top_builddir)/tests/lib/libfolks-test.la \
+ $(GLIB_LIBS) \
+ $(GEE_LIBS) \
+ $(NULL)
+
+EXTRA_DIST = \
+ bluez-test.vapi \
+ bluez-test.h \
+ $(NULL)
+
+-include $(top_srcdir)/git.mk
diff --git a/tests/lib/bluez/backend.vala b/tests/lib/bluez/backend.vala
new file mode 100644
index 00000000..1ba34a2a
--- /dev/null
+++ b/tests/lib/bluez/backend.vala
@@ -0,0 +1,306 @@
+/*
+ * Copyright (C) 2013 Collabora Ltd.
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Philip Withnall <philip.withnall@collabora.co.uk>
+ */
+
+using GLib;
+
+/* Specific mock interfaces for the BlueZ and OBEX services. */
+namespace org
+ {
+ namespace bluez
+ {
+ /* Interface for the bluez5 python-dbusmock template. */
+ [DBus (name = "org.bluez.Mock")]
+ public interface Mock : Object
+ {
+ [DBus (name = "AddAdapter")]
+ public abstract string add_adapter (string device_name,
+ string system_name) throws IOError;
+
+ [DBus (name = "AddDevice")]
+ public abstract string add_device (string adapter_device_name,
+ string device_address, string alias) throws IOError;
+
+ [DBus (name = "PairDevice")]
+ public abstract void pair_device (string adapter_device_name,
+ string device_address) throws IOError;
+
+ [DBus (name = "BlockDevice")]
+ public abstract void block_device (string adapter_device_name,
+ string device_address) throws IOError;
+ }
+
+ namespace obex
+ {
+ /* Interface for the bluez5-obex python-dbusmock template. */
+ [DBus (name = "org.bluez.obex.Mock")]
+ public interface Mock : Object
+ {
+ [DBus (name = "TransferCreated")]
+ public abstract signal void transfer_created (string path,
+ HashTable<string, Variant> filters,
+ string transfer_filename);
+ }
+
+ namespace transfer1
+ {
+ [DBus (name = "org.bluez.obex.transfer1.Mock")]
+ public interface Mock : Object
+ {
+ [DBus (name = "UpdateStatus")]
+ public abstract void update_status (bool is_complete)
+ throws IOError;
+ }
+ }
+ }
+ }
+ }
+
+/**
+ * Controller for a mock BlueZ backend.
+ *
+ * This contains control methods to instantiate and manipulate a mock BlueZ
+ * service over D-Bus, for the purposes of testing the folks BlueZ backend.
+ *
+ * The mock service uses python-dbusmock, with control messages being sent to
+ * ``*.Mock`` interfaces on the D-Bus objects. Those control interfaces are
+ * exposed as {@link Backend.mock_bluez}, {@link Backend.mock_bluez_base},
+ * {@link Backend.mock_obex} and {@link Backend.mock_obex_base}.
+ *
+ * @since UNRELEASED
+ */
+public class BluezTest.Backend
+{
+ private org.bluez.Mock? _mock_bluez = null;
+ private org.freedesktop.DBus.Mock? _mock_bluez_base = null;
+ private org.bluez.obex.Mock? _mock_obex = null;
+ private org.freedesktop.DBus.Mock? _mock_obex_base = null;
+
+ /**
+ * D-Bus proxy for the BlueZ-specific mock interface on the org.bluez object.
+ *
+ * @since UNRELEASED
+ */
+ public org.bluez.Mock? mock_bluez
+ {
+ get { return this._mock_bluez; }
+ }
+
+ /**
+ * D-Bus proxy for the dbusmock mock interface on the org.bluez object.
+ *
+ * @since UNRELEASED
+ */
+ public org.freedesktop.DBus.Mock? mock_bluez_base
+ {
+ get { return this._mock_bluez_base; }
+ }
+
+ /**
+ * D-Bus proxy for the BlueZ-specific mock interface on the org.bluez.obex
+ * object.
+ *
+ * @since UNRELEASED
+ */
+ public org.bluez.obex.Mock? mock_obex
+ {
+ get { return this._mock_obex; }
+ }
+
+ /**
+ * D-Bus proxy for the dbusmock mock interface on the org.bluez.obex object.
+ *
+ * @since UNRELEASED
+ */
+ public org.freedesktop.DBus.Mock? mock_obex_base
+ {
+ get { return this._mock_obex_base; }
+ }
+
+ /**
+ * Default Bluetooth address used for the primary adapter.
+ *
+ * This is the address used for the primary Bluetooth adapter (``hci0``)
+ * unless otherwise specified.
+ *
+ * @since UNRELEASED
+ */
+ public string primary_device_address
+ {
+ get { return "00:00:00:00:00:00"; }
+ }
+
+ /**
+ * Set up the mock D-Bus interfaces.
+ *
+ * This must be called before every different unit test. It creates D-Bus
+ * proxies for the dbusmock objects, auto-launching python-dbusmock if
+ * necessary.
+ *
+ * The required D-Bus service files must previously have been set up with the
+ * buses which are in use. This is done in
+ * {@link TestCase.create_transient_dir}.
+ *
+ * @since UNRELEASED
+ */
+ public void set_up ()
+ {
+ /* Create proxies for the client code to use. This auto-starts the
+ * services. Their service files are created in TestCase. */
+ try
+ {
+ this._mock_bluez =
+ Bus.get_proxy_sync (BusType.SYSTEM, "org.bluez", "/");
+ this._mock_bluez_base =
+ Bus.get_proxy_sync (BusType.SYSTEM, "org.bluez", "/");
+
+ this._mock_obex =
+ Bus.get_proxy_sync (BusType.SESSION, "org.bluez.obex", "/");
+ this._mock_obex_base =
+ Bus.get_proxy_sync (BusType.SESSION, "org.bluez.obex", "/");
+ }
+ catch (GLib.Error e1)
+ {
+ /* Tidy up. */
+ this.tear_down ();
+
+ error ("Error connecting to mock object: %s", e1.message);
+ }
+ }
+
+ /**
+ * Tear down the mock D-Bus interfaces.
+ *
+ * This must be called after every different unit test. It undoes
+ * {@link Backend.set_up}, although the python-dbusmock processes are kept
+ * around and reset, rather than being killed.
+ *
+ * @since UNRELEASED
+ */
+ public void tear_down ()
+ {
+ /* Reset the python-dbusmock state. */
+ try
+ {
+ this._mock_obex_base.reset ();
+ this._mock_bluez_base.reset ();
+ }
+ catch (IOError e1)
+ {
+ error ("Error resetting python-dbusmock state: %s", e1.message);
+ }
+
+ /* Remove the D-Bus proxies. The python-dbusmock instances will close by
+ * themselves when the mock D-Bus buses are destroyed in
+ * final_tear_down(). */
+ this._mock_obex_base = null;
+ this._mock_bluez_base = null;
+ this._mock_obex = null;
+ this._mock_bluez = null;
+ }
+
+ /**
+ * Create a simple Bluetooth device with the given vCard.
+ *
+ * Create a new Bluetooth adapter (``hci0``) and a new Bluetooth device (with
+ * address {@link Backend.primary_device_address}). Pair with the Bluetooth
+ * device and simulate it having the given ``vcard`` (potentially containing
+ * multiple whitespace-separated entries) as its address book.
+ *
+ * On error this function will abort the test.
+ *
+ * @param vcard series of vCards for the device’s address book
+ * @param adapter_path optional return location for the adapter’s D-Bus object
+ * path
+ * @param device_path optional return location for the device’s D-Bus object
+ * path
+ * @return ID of the signal returning the vCard, as per
+ * {@link Backend.set_simple_device_vcard}
+ *
+ * @since UNRELEASED
+ */
+ public ulong create_simple_device_with_vcard (string vcard,
+ out string? adapter_path = null, out string? device_path = null)
+ {
+ try
+ {
+ /* Set up a Bluetooth adapter and a single persona store. */
+ adapter_path = this.mock_bluez.add_adapter ("hci0", "Test System");
+ device_path =
+ this.mock_bluez.add_device ("hci0", this.primary_device_address,
+ "My Phone");
+
+ /* Pair with the phone. */
+ this.mock_bluez.pair_device ("hci0", this.primary_device_address);
+
+ /* Set the vCard to be returned for all transfers. */
+ return this.set_simple_device_vcard (vcard);
+ }
+ catch (IOError e1)
+ {
+ error ("Error setting up mock BlueZ device: %s", e1.message);
+ }
+ }
+
+ /**
+ * Set the vCard to be returned by a simple Bluetooth device.
+ *
+ * This sets the vCard which will be returned indefinitely. It returns a
+ * signal ID which may be disconnected with:
+ * {{{
+ * this.mock_obex.disconnect (signal_id);
+ * }}}
+ * to prevent the vCard being returned in future.
+ *
+ * @param vcard series of vCards for the device’s address book
+ * @return ID of the signal returning the vCard
+ *
+ * @since UNRELEASED
+ */
+ public ulong set_simple_device_vcard (string vcard)
+ {
+ /* Wait for a transfer to be created. Skip activating it and go
+ * straight to completion. */
+ return this.mock_obex.transfer_created.connect ((p, f, v) =>
+ {
+ org.bluez.obex.transfer1.Mock proxy;
+
+ try
+ {
+ FileUtils.set_contents (v, vcard);
+ }
+ catch (FileError e1)
+ {
+ error ("Error writing vCard transfer file ‘%s’: %s",
+ v, e1.message);
+ }
+
+ try
+ {
+ proxy =
+ Bus.get_proxy_sync (BusType.SESSION, "org.bluez.obex", p);
+ proxy.update_status (true);
+ }
+ catch (GLib.Error e1)
+ {
+ error ("Error activating transfer: %s", e1.message);
+ }
+ });
+ }
+}
diff --git a/tests/lib/bluez/test-case.vala b/tests/lib/bluez/test-case.vala
new file mode 100644
index 00000000..accaf0b1
--- /dev/null
+++ b/tests/lib/bluez/test-case.vala
@@ -0,0 +1,127 @@
+/*
+ * Copyright © 2013 Collabora Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Author:
+ * Philip Withnall <philip.withnall@collabora.co.uk>
+ */
+
+/**
+ * A test case for the BlueZ backend, whose private D-Bus session contains the
+ * necessary python-dbusmock instance to mock up BlueZ.
+ *
+ * @since UNRELEASED
+ */
+public class BluezTest.TestCase : Folks.TestCase
+{
+ /**
+ * A BlueZ backend, normally non-null between set_up() and tear_down().
+ *
+ * If this is non-null, the subclass is expected to have called
+ * its set_up() method at some point before tear_down() is reached.
+ * This usually happens in create_backend().
+ */
+ public BluezTest.Backend? bluez_backend = null;
+
+ public TestCase (string name)
+ {
+ base (name);
+
+ this.bluez_backend = new BluezTest.Backend ();
+
+ Environment.set_variable ("FOLKS_BACKENDS_ALLOWED", "bluez", true);
+ Environment.set_variable ("FOLKS_PRIMARY_STORE", "bluez", true);
+ Environment.set_variable ("FOLKS_BLUEZ_TIMEOUT_DIVISOR", "100", true);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @since UNRELEASED
+ */
+ public override void set_up ()
+ {
+ base.set_up ();
+ this.create_backend ();
+ this.configure_primary_store ();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @since UNRELEASED
+ */
+ public override void private_bus_up ()
+ {
+ /* Set up service files for the python-dbusmock services. */
+ this.create_dbusmock_service (BusType.SYSTEM, "org.bluez", "bluez5");
+ this.create_dbusmock_service (BusType.SESSION, "org.bluez.obex",
+ "bluez5-obex");
+
+ base.private_bus_up ();
+ }
+
+ /**
+ * Virtual method to create and set up the BlueZ backend.
+ *
+ * Called from set_up(); may be overridden to not create the backend,
+ * or to create it but not set it up.
+ *
+ * Subclasses may chain up, but are not required to so.
+ *
+ * @since UNRELEASED
+ */
+ public virtual void create_backend ()
+ {
+ this.bluez_backend = new BluezTest.Backend ();
+ ((!) this.bluez_backend).set_up ();
+ }
+
+ /**
+ * Virtual method to configure ``FOLKS_PRIMARY_STORE`` to point to
+ * our //bluez_backend//.
+ *
+ * Subclasses may chain up, but are not required to so.
+ *
+ * @since UNRELEASED
+ */
+ public virtual void configure_primary_store ()
+ {
+ /* By default, configure BlueZ as the primary store. */
+ assert (this.bluez_backend != null);
+ var config_val =
+ "bluez:" + ((!) this.bluez_backend).primary_device_address;
+ Environment.set_variable ("FOLKS_PRIMARY_STORE", config_val, true);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @since UNRELEASED
+ */
+ public override void tear_down ()
+ {
+ if (this.bluez_backend != null)
+ {
+ ((!) this.bluez_backend).tear_down ();
+ this.bluez_backend = null;
+ }
+
+ Environment.unset_variable ("FOLKS_PRIMARY_STORE");
+
+ base.tear_down ();
+ }
+}
diff --git a/tests/lib/dummy/Makefile.am b/tests/lib/dummy/Makefile.am
index 11610043..71c4ec80 100644
--- a/tests/lib/dummy/Makefile.am
+++ b/tests/lib/dummy/Makefile.am
@@ -18,6 +18,7 @@ libdummy_test_la_VALAFLAGS = \
--pkg folks \
--pkg folks-dummy \
--pkg folks-test \
+ --pkg folks-test-dbus \
-g \
$(NULL)
diff --git a/tests/lib/eds/Makefile.am b/tests/lib/eds/Makefile.am
index dddb57f0..ce83750b 100644
--- a/tests/lib/eds/Makefile.am
+++ b/tests/lib/eds/Makefile.am
@@ -22,6 +22,7 @@ libeds_test_la_VALAFLAGS = \
--pkg libxml-2.0 \
--pkg folks-eds \
--pkg folks-test \
+ --pkg folks-test-dbus \
-g \
$(NULL)
diff --git a/tests/lib/eds/test-case.vala b/tests/lib/eds/test-case.vala
index 456f46f4..bc36d449 100644
--- a/tests/lib/eds/test-case.vala
+++ b/tests/lib/eds/test-case.vala
@@ -26,8 +26,14 @@
* A test case whose private D-Bus session contains the necessary daemons
* for an Evolution address-book.
*
- * FIXME: For now, this relies on running under with-session-bus-eds.sh
- * with FOLKS_BACKEND_PATH set.
+ * The EDS daemons are started through D-Bus service activation in
+ * {@link TestCase.private_bus_up}, and should automatically exit when the mock
+ * D-Bus bus is torn down. All of their configuration and data storage is
+ * isolated in a temporary directory which is unique per test run.
+ *
+ * The EDS daemons are only torn down in {@link TestCase.final_tear_down}, so
+ * remain running between test cases in the same test binary. Their state is
+ * soft-reset, but some state may be retained between test cases.
*/
public class EdsTest.TestCase : Folks.TestCase
{
@@ -42,14 +48,6 @@ public class EdsTest.TestCase : Folks.TestCase
public TestCase (string name)
{
- /* This variable is set in the same place as the various variables we
- * care about for sandboxing purposes, like XDG_CONFIG_HOME and
- * DBUS_SESSION_BUS_ADDRESS. */
- if (Environment.get_variable ("FOLKS_TESTS_SANDBOXED_DBUS")
- != "eds")
- error ("e-d-s tests must be run in a private D-Bus session " +
- "with e-d-s services");
-
base (name);
Environment.set_variable ("FOLKS_BACKENDS_ALLOWED", "eds", true);
@@ -57,17 +55,83 @@ public class EdsTest.TestCase : Folks.TestCase
true);
}
- public override string? create_transient_dir ()
+ public override string create_transient_dir ()
{
- /* Don't do anything. We're currently relying on
- * being wrapped in with-session-bus-eds.sh. */
- return null;
+ var transient = base.create_transient_dir ();
+
+ /* Evolution configuration directory. */
+ var config_dir = "%s/.config/evolution/sources".printf (transient);
+
+ if (GLib.DirUtils.create_with_parents (config_dir, 0700) != 0)
+ error ("unable to create '%s': %s",
+ config_dir, GLib.strerror (GLib.errno));
+
+ return transient;
}
public override void private_bus_up ()
{
- /* Don't do anything. We're currently relying on
- * being wrapped in with-session-bus-eds.sh. */
+ base.private_bus_up ();
+
+ /* Find out the libexec directory to use. */
+ int exit_status = -1;
+ string capture_stdout = null;
+
+ try
+ {
+ Process.spawn_sync (null /* cwd */,
+ { "pkg-config", "--variable=libexecdir", "libedata-book-1.2" },
+ null /* envp */,
+ SpawnFlags.SEARCH_PATH /* flags */,
+ null /* child setup */,
+ out capture_stdout,
+ null /* do not capture stderr */,
+ out exit_status);
+
+ Process.check_exit_status (exit_status);
+ }
+ catch (GLib.Error e1)
+ {
+ error ("Error getting libexecdir from pkg-config: %s", e1.message);
+ }
+
+ var libexec = capture_stdout.strip ();
+
+ /* Create service files for the Evolution binaries. */
+ var service_file_name =
+ Path.build_filename (this.transient_dir, "dbus-1", "services",
+ "evolution-source-registry.service");
+ var service_file = ("[D-BUS Service]\n" +
+ "Name=org.gnome.evolution.dataserver.Sources3\n" +
+ "Exec=%s/evolution-source-registry\n").printf (libexec);
+
+ try
+ {
+ FileUtils.set_contents (service_file_name, service_file);
+ }
+ catch (FileError e2)
+ {
+ error ("Error creating D-Bus service file ‘%s’: %s",
+ service_file_name, e2.message);
+ }
+
+ /* Address book factory. */
+ service_file_name =
+ Path.build_filename (this.transient_dir, "dbus-1", "services",
+ "evolution-addressbook-factory.service");
+ service_file = ("[D-BUS Service]\n" +
+ "Name=org.gnome.evolution.dataserver.AddressBook6\n" +
+ "Exec=%s/evolution-addressbook-factory\n").printf (libexec);
+
+ try
+ {
+ FileUtils.set_contents (service_file_name, service_file);
+ }
+ catch (FileError e3)
+ {
+ error ("Error creating D-Bus service file ‘%s’: %s",
+ service_file_name, e3.message);
+ }
}
public override void set_up ()
diff --git a/tests/lib/folks-test-dbus.vapi b/tests/lib/folks-test-dbus.vapi
new file mode 100644
index 00000000..bc005ebb
--- /dev/null
+++ b/tests/lib/folks-test-dbus.vapi
@@ -0,0 +1,52 @@
+/*
+ * folks-test-dbus.vapi — a tweaked copy of GTestDBus wrapped in Vala
+ *
+ * Copyright © 2014 Philip Withnall
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ *
+ * Authors:
+ * Philip Withnall <philip@tecnocode.co.uk>
+ */
+
+[CCode (gir_namespace = "Folks", gir_version = "0.6")]
+namespace Folks
+{
+ [CCode (cheader_filename = "gtestdbus.h", cprefix = "FOLKS_TEST_DBUS_")]
+ [Flags]
+ public enum TestDBusFlags {
+ NONE,
+ SESSION_BUS,
+ SYSTEM_BUS
+ }
+
+ [CCode (cheader_filename = "gtestdbus.h")]
+ public class TestDBus : GLib.Object
+ {
+ [CCode (has_construct_function = false)]
+ public TestDBus (Folks.TestDBusFlags flags);
+ public void add_service_dir (string path);
+ public void down ();
+ public unowned string get_bus_address ();
+ public Folks.TestDBusFlags get_flags ();
+ public void stop ();
+ public static void unset ();
+ public void up ();
+ public Folks.TestDBusFlags flags { get; construct; }
+ }
+}
+
+/* vim:set ft=vala: */
diff --git a/tests/lib/gtestdbus.c b/tests/lib/gtestdbus.c
new file mode 100644
index 00000000..cca9435a
--- /dev/null
+++ b/tests/lib/gtestdbus.c
@@ -0,0 +1,941 @@
+/* GIO testing utilities
+ *
+ * Copyright (C) 2008-2010 Red Hat, Inc.
+ * Copyright (C) 2012 Collabora Ltd. <http://www.collabora.co.uk/>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: David Zeuthen <davidz@redhat.com>
+ * Xavier Claessens <xavier.claessens@collabora.co.uk>
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <glib/gstdio.h>
+#ifdef G_OS_UNIX
+#include <unistd.h>
+#endif
+#ifdef G_OS_WIN32
+#include <io.h>
+#endif
+
+#include <glib.h>
+#include <gio/gio.h>
+
+#include "gtestdbus.h"
+
+#ifdef G_OS_WIN32
+#include <windows.h>
+#endif
+
+GType
+folks_test_dbus_flags_get_type (void)
+{
+ static volatile gsize g_define_type_id__volatile = 0;
+
+ if (g_once_init_enter (&g_define_type_id__volatile))
+ {
+ static const GFlagsValue values[] = {
+ { FOLKS_TEST_DBUS_NONE, "FOLKS_TEST_DBUS_NONE", "none" },
+ { FOLKS_TEST_DBUS_SESSION_BUS, "FOLKS_TEST_DBUS_SESSION_BUS", "session-bus" },
+ { FOLKS_TEST_DBUS_SYSTEM_BUS, "FOLKS_TEST_DBUS_SYSTEM_BUS", "system-bus" },
+ { 0, NULL, NULL }
+ };
+ GType g_define_type_id =
+ g_flags_register_static (g_intern_static_string ("FolksTestDBusFlags"), values);
+ g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+ }
+
+ return g_define_type_id__volatile;
+}
+
+/* -------------------------------------------------------------------------- */
+/* Utility: Wait until object has a single ref */
+
+typedef struct
+{
+ GMainLoop *loop;
+ gboolean timed_out;
+} WeakNotifyData;
+
+static gboolean
+on_weak_notify_timeout (gpointer user_data)
+{
+ WeakNotifyData *data = user_data;
+ data->timed_out = TRUE;
+ g_main_loop_quit (data->loop);
+ return FALSE;
+}
+
+static gboolean
+dispose_on_idle (gpointer object)
+{
+ g_object_run_dispose (object);
+ g_object_unref (object);
+ return FALSE;
+}
+
+static gboolean
+_g_object_dispose_and_wait_weak_notify (gpointer object)
+{
+ WeakNotifyData data;
+ guint timeout_id;
+
+ data.loop = g_main_loop_new (NULL, FALSE);
+ data.timed_out = FALSE;
+
+ g_object_weak_ref (object, (GWeakNotify) g_main_loop_quit, data.loop);
+
+ /* Drop the ref in an idle callback, this is to make sure the mainloop
+ * is already running when weak notify happens */
+ g_idle_add (dispose_on_idle, object);
+
+ /* Make sure we don't block forever */
+ timeout_id = g_timeout_add (30 * 1000, on_weak_notify_timeout, &data);
+
+ g_main_loop_run (data.loop);
+
+ if (data.timed_out)
+ {
+ g_warning ("Weak notify timeout, object ref_count=%d\n",
+ G_OBJECT (object)->ref_count);
+ }
+ else
+ {
+ g_source_remove (timeout_id);
+ }
+
+ g_main_loop_unref (data.loop);
+ return data.timed_out;
+}
+
+/* -------------------------------------------------------------------------- */
+/* Utilities to cleanup the mess in the case unit test process crash */
+
+#ifdef G_OS_WIN32
+
+/* This could be interesting to expose in public API */
+static void
+_folks_test_watcher_add_pid (GPid pid)
+{
+ static gsize started = 0;
+ HANDLE job;
+
+ if (g_once_init_enter (&started))
+ {
+ JOBOBJECT_EXTENDED_LIMIT_INFORMATION info;
+
+ job = CreateJobObjectW (NULL, NULL);
+ memset (&info, 0, sizeof (info));
+ info.BasicLimitInformation.LimitFlags = 0x2000 /* JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE */;
+
+ if (!SetInformationJobObject(job, JobObjectExtendedLimitInformation, &info, sizeof (info)))
+ g_warning ("Can't enable JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE: %s", g_win32_error_message (GetLastError()));
+
+ g_once_init_leave (&started,(gsize)job);
+ }
+
+ job = (HANDLE)started;
+
+ if (!AssignProcessToJobObject(job, pid))
+ g_warning ("Can't assign process to job: %s", g_win32_error_message (GetLastError()));
+}
+
+static void
+_folks_test_watcher_remove_pid (GPid pid)
+{
+ /* No need to unassign the process from the job object as the process
+ will be killed anyway */
+}
+
+#else
+
+#define ADD_PID_FORMAT "add pid %d\n"
+#define REMOVE_PID_FORMAT "remove pid %d\n"
+
+static void
+watch_parent (gint fd)
+{
+ GIOChannel *channel;
+ GPollFD fds[1];
+ GArray *pids_to_kill;
+
+ channel = g_io_channel_unix_new (fd);
+
+ fds[0].fd = fd;
+ fds[0].events = G_IO_HUP | G_IO_IN;
+ fds[0].revents = 0;
+
+ pids_to_kill = g_array_new (FALSE, FALSE, sizeof (guint));
+
+ do
+ {
+ gint num_events;
+ gchar *command = NULL;
+ guint pid;
+ guint n;
+ GError *error = NULL;
+
+ num_events = g_poll (fds, 1, -1);
+ if (num_events == 0)
+ continue;
+
+ if (fds[0].revents == G_IO_HUP)
+ {
+ /* Parent quit, cleanup the mess and exit */
+ for (n = 0; n < pids_to_kill->len; n++)
+ {
+ pid = g_array_index (pids_to_kill, guint, n);
+ g_print ("cleaning up pid %d\n", pid);
+ kill (pid, SIGTERM);
+ }
+
+ g_array_unref (pids_to_kill);
+ g_io_channel_shutdown (channel, FALSE, &error);
+ g_assert_no_error (error);
+ g_io_channel_unref (channel);
+
+ exit (0);
+ }
+
+ /* Read the command from the input */
+ g_io_channel_read_line (channel, &command, NULL, NULL, &error);
+ g_assert_no_error (error);
+
+ /* Check for known commands */
+ if (sscanf (command, ADD_PID_FORMAT, &pid) == 1)
+ {
+ g_array_append_val (pids_to_kill, pid);
+ }
+ else if (sscanf (command, REMOVE_PID_FORMAT, &pid) == 1)
+ {
+ for (n = 0; n < pids_to_kill->len; n++)
+ {
+ if (g_array_index (pids_to_kill, guint, n) == pid)
+ {
+ g_array_remove_index (pids_to_kill, n);
+ pid = 0;
+ break;
+ }
+ }
+ if (pid != 0)
+ {
+ g_warning ("unknown pid %d to remove", pid);
+ }
+ }
+ else
+ {
+ g_warning ("unknown command from parent '%s'", command);
+ }
+
+ g_free (command);
+ }
+ while (TRUE);
+}
+
+static GIOChannel *
+watcher_init (void)
+{
+ static gsize started = 0;
+ static GIOChannel *channel = NULL;
+
+ if (g_once_init_enter (&started))
+ {
+ gint pipe_fds[2];
+
+ /* fork a child to clean up when we are killed */
+ if (pipe (pipe_fds) != 0)
+ {
+ g_warning ("pipe() failed: %m");
+ g_assert_not_reached ();
+ }
+
+ switch (fork ())
+ {
+ case -1:
+ g_warning ("fork() failed: %m");
+ g_assert_not_reached ();
+ break;
+
+ case 0:
+ /* child */
+ close (pipe_fds[1]);
+ watch_parent (pipe_fds[0]);
+ break;
+
+ default:
+ /* parent */
+ close (pipe_fds[0]);
+ channel = g_io_channel_unix_new (pipe_fds[1]);
+ }
+
+ g_once_init_leave (&started, 1);
+ }
+
+ return channel;
+}
+
+static void
+watcher_send_command (const gchar *command)
+{
+ GIOChannel *channel;
+ GError *error = NULL;
+
+ channel = watcher_init ();
+
+ g_io_channel_write_chars (channel, command, -1, NULL, &error);
+ g_assert_no_error (error);
+
+ g_io_channel_flush (channel, &error);
+ g_assert_no_error (error);
+}
+
+/* This could be interesting to expose in public API */
+static void
+_folks_test_watcher_add_pid (GPid pid)
+{
+ gchar *command;
+
+ command = g_strdup_printf (ADD_PID_FORMAT, (guint) pid);
+ watcher_send_command (command);
+ g_free (command);
+}
+
+static void
+_folks_test_watcher_remove_pid (GPid pid)
+{
+ gchar *command;
+
+ command = g_strdup_printf (REMOVE_PID_FORMAT, (guint) pid);
+ watcher_send_command (command);
+ g_free (command);
+}
+
+#endif
+
+/* -------------------------------------------------------------------------- */
+/* FolksTestDBus object implementation */
+
+/**
+ * SECTION:folkstestdbus
+ * @short_description: D-Bus testing helper
+ * @include: gio/gio.h
+ *
+ * A helper class for testing code which uses D-Bus without touching the user's
+ * system or session bus.
+ *
+ * Note that #FolksTestDBus modifies the user’s environment, calling setenv().
+ * This is not thread-safe, so all #FolksTestDBus calls should be completed before
+ * threads are spawned, or should have appropriate locking to ensure no access
+ * conflicts to environment variables shared between #FolksTestDBus and other
+ * threads.
+ *
+ * ## Creating unit tests using FolksTestDBus
+ *
+ * Testing of D-Bus services can be tricky because normally we only ever run
+ * D-Bus services over an existing instance of the D-Bus daemon thus we
+ * usually don't activate D-Bus services that are not yet installed into the
+ * target system. The #FolksTestDBus object makes this easier for us by taking care
+ * of the lower level tasks such as running a private D-Bus daemon and looking
+ * up uninstalled services in customizable locations, typically in your source
+ * code tree.
+ *
+ * The first thing you will need is a separate service description file for the
+ * D-Bus daemon. Typically a `services` subdirectory of your `tests` directory
+ * is a good place to put this file.
+ *
+ * The service file should list your service along with an absolute path to the
+ * uninstalled service executable in your source tree. Using autotools we would
+ * achieve this by adding a file such as `my-server.service.in` in the services
+ * directory and have it processed by configure.
+ * |[
+ * [D-BUS Service]
+ * Name=org.gtk.GDBus.Examples.ObjectManager
+ * Exec=@abs_top_builddir@/gio/tests/gdbus-example-objectmanager-server
+ * ]|
+ * You will also need to indicate this service directory in your test
+ * fixtures, so you will need to pass the path while compiling your
+ * test cases. Typically this is done with autotools with an added
+ * preprocessor flag specified to compile your tests such as:
+ * |[
+ * -DTEST_SERVICES=\""$(abs_top_builddir)/tests/services"\"
+ * ]|
+ * Once you have a service definition file which is local to your source tree,
+ * you can proceed to set up a GTest fixture using the #FolksTestDBus scaffolding.
+ *
+ * An example of a test fixture for D-Bus services can be found
+ * here:
+ * [gdbus-test-fixture.c](https://git.gnome.org/browse/glib/tree/gio/tests/gdbus-test-fixture.c)
+ *
+ * The default behaviour is to create a session bus. The
+ * %FOLKS_TEST_DBUS_SESSION_BUS flag may be specified to clarify this, but it
+ * isn’t required.
+ *
+ * If your service needs to run on the system bus, rather than the session
+ * bus, pass the %FOLKS_TEST_DBUS_SYSTEM_BUS flag to folks_test_dbus_new(). This
+ * will create an isolated system bus. Using two #GTestDBus instances, one
+ * with this flag set and one without, a unit test can use isolated services
+ * on both the system and session buses.
+ *
+ * Note that these examples only deal with isolating the D-Bus aspect of your
+ * service. To successfully run isolated unit tests on your service you may need
+ * some additional modifications to your test case fixture. For example; if your
+ * service uses GSettings and installs a schema then it is important that your test service
+ * not load the schema in the ordinary installed location (chances are that your service
+ * and schema files are not yet installed, or worse; there is an older version of the
+ * schema file sitting in the install location).
+ *
+ * Most of the time we can work around these obstacles using the
+ * environment. Since the environment is inherited by the D-Bus daemon
+ * created by #FolksTestDBus and then in turn inherited by any services the
+ * D-Bus daemon activates, using the setup routine for your fixture is
+ * a practical place to help sandbox your runtime environment. For the
+ * rather typical GSettings case we can work around this by setting
+ * `GSETTINGS_SCHEMA_DIR` to the in tree directory holding your schemas
+ * in the above fixture_setup() routine.
+ *
+ * The GSettings schemas need to be locally pre-compiled for this to work. This can be achieved
+ * by compiling the schemas locally as a step before running test cases, an autotools setup might
+ * do the following in the directory holding schemas:
+ * |[
+ * all-am:
+ * $(GLIB_COMPILE_SCHEMAS) .
+ *
+ * CLEANFILES += gschemas.compiled
+ * ]|
+ */
+
+typedef struct _FolksTestDBusClass FolksTestDBusClass;
+typedef struct _FolksTestDBusPrivate FolksTestDBusPrivate;
+
+/**
+ * FolksTestDBus:
+ *
+ * The #FolksTestDBus structure contains only private data and
+ * should only be accessed using the provided API.
+ *
+ * Since: 2.34
+ */
+struct _FolksTestDBus {
+ GObject parent;
+
+ FolksTestDBusPrivate *priv;
+};
+
+struct _FolksTestDBusClass {
+ GObjectClass parent_class;
+};
+
+struct _FolksTestDBusPrivate
+{
+ FolksTestDBusFlags flags;
+ GPtrArray *service_dirs;
+ GPid bus_pid;
+ gchar *bus_address;
+ gboolean up;
+};
+
+enum
+{
+ PROP_0,
+ PROP_FLAGS,
+};
+
+G_DEFINE_TYPE_WITH_PRIVATE (FolksTestDBus, folks_test_dbus, G_TYPE_OBJECT)
+
+static void
+folks_test_dbus_init (FolksTestDBus *self)
+{
+ self->priv = folks_test_dbus_get_instance_private (self);
+ self->priv->service_dirs = g_ptr_array_new_with_free_func (g_free);
+}
+
+static void
+folks_test_dbus_dispose (GObject *object)
+{
+ FolksTestDBus *self = (FolksTestDBus *) object;
+
+ if (self->priv->up)
+ folks_test_dbus_down (self);
+
+ G_OBJECT_CLASS (folks_test_dbus_parent_class)->dispose (object);
+}
+
+static void
+folks_test_dbus_finalize (GObject *object)
+{
+ FolksTestDBus *self = (FolksTestDBus *) object;
+
+ g_ptr_array_unref (self->priv->service_dirs);
+ g_free (self->priv->bus_address);
+
+ G_OBJECT_CLASS (folks_test_dbus_parent_class)->finalize (object);
+}
+
+static void
+folks_test_dbus_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ FolksTestDBus *self = (FolksTestDBus *) object;
+
+ switch (property_id)
+ {
+ case PROP_FLAGS:
+ g_value_set_flags (value, folks_test_dbus_get_flags (self));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+folks_test_dbus_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ FolksTestDBus *self = (FolksTestDBus *) object;
+
+ switch (property_id)
+ {
+ case PROP_FLAGS:
+ self->priv->flags = g_value_get_flags (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+folks_test_dbus_class_init (FolksTestDBusClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->dispose = folks_test_dbus_dispose;
+ object_class->finalize = folks_test_dbus_finalize;
+ object_class->get_property = folks_test_dbus_get_property;
+ object_class->set_property = folks_test_dbus_set_property;
+
+ /**
+ * FolksTestDBus:flags:
+ *
+ * #FolksTestDBusFlags specifying the behaviour of the D-Bus session.
+ *
+ * Since: 2.34
+ */
+ g_object_class_install_property (object_class, PROP_FLAGS,
+ g_param_spec_flags ("flags",
+ "D-Bus session flags",
+ "Flags specifying the behaviour of the D-Bus session",
+ FOLKS_TYPE_TEST_DBUS_FLAGS, FOLKS_TEST_DBUS_NONE,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
+
+}
+
+static gchar *
+write_config_file (FolksTestDBus *self)
+{
+ GString *contents;
+ gint fd;
+ guint i;
+ GError *error = NULL;
+ gchar *path = NULL;
+
+ fd = g_file_open_tmp ("g-test-dbus-XXXXXX", &path, &error);
+ g_assert_no_error (error);
+
+ contents = g_string_new (NULL);
+ g_string_append (contents,
+ "<busconfig>\n"
+#ifdef G_OS_WIN32
+ " <listen>nonce-tcp:</listen>\n"
+#else
+ " <listen>unix:tmpdir=/tmp</listen>\n"
+#endif
+ );
+
+ if (self->priv->flags & FOLKS_TEST_DBUS_SYSTEM_BUS)
+ {
+ g_string_append (contents,
+ " <type>system</type>\n");
+ }
+ else
+ {
+ g_string_append (contents,
+ " <type>session</type>\n");
+ }
+
+ for (i = 0; i < self->priv->service_dirs->len; i++)
+ {
+ const gchar *dir_path = g_ptr_array_index (self->priv->service_dirs, i);
+
+ g_string_append_printf (contents,
+ " <servicedir>%s</servicedir>\n", dir_path);
+ }
+
+ g_string_append (contents,
+ " <policy context=\"default\">\n"
+ " <!-- Allow everything to be sent -->\n"
+ " <allow send_destination=\"*\" eavesdrop=\"true\"/>\n"
+ " <!-- Allow everything to be received -->\n"
+ " <allow eavesdrop=\"true\"/>\n"
+ " <!-- Allow anyone to own anything -->\n"
+ " <allow own=\"*\"/>\n"
+ " </policy>\n"
+ "</busconfig>\n");
+
+ g_file_set_contents (path, contents->str, contents->len, &error);
+ g_assert_no_error (error);
+
+ g_string_free (contents, TRUE);
+
+ close (fd);
+
+ return path;
+}
+
+static void
+start_daemon (FolksTestDBus *self)
+{
+ const gchar *argv[] = {"dbus-daemon", "--print-address", "--config-file=foo", NULL};
+ gchar *config_path;
+ gchar *config_arg;
+ gint stdout_fd;
+ GIOChannel *channel;
+ gsize termpos;
+ GError *error = NULL;
+
+ if (g_getenv ("G_TEST_DBUS_DAEMON") != NULL)
+ argv[0] = (gchar *)g_getenv ("G_TEST_DBUS_DAEMON");
+
+ /* Write config file and set its path in argv */
+ config_path = write_config_file (self);
+ config_arg = g_strdup_printf ("--config-file=%s", config_path);
+ argv[2] = config_arg;
+
+ /* Spawn dbus-daemon */
+ g_spawn_async_with_pipes (NULL,
+ (gchar **) argv,
+ NULL,
+#ifdef G_OS_WIN32
+ /* We Need this to get the pid returned on win32 */
+ G_SPAWN_DO_NOT_REAP_CHILD |
+#endif
+ G_SPAWN_SEARCH_PATH,
+ NULL,
+ NULL,
+ &self->priv->bus_pid,
+ NULL,
+ &stdout_fd,
+ NULL,
+ &error);
+ g_assert_no_error (error);
+
+ _folks_test_watcher_add_pid (self->priv->bus_pid);
+
+ /* Read bus address from daemon' stdout */
+ channel = g_io_channel_unix_new (stdout_fd);
+ g_io_channel_read_line (channel, &self->priv->bus_address, NULL,
+ &termpos, &error);
+ g_assert_no_error (error);
+ self->priv->bus_address[termpos] = '\0';
+
+ /* start dbus-monitor */
+ if (g_getenv ("G_DBUS_MONITOR") != NULL)
+ {
+ gchar *command;
+
+ command = g_strdup_printf ("dbus-monitor --address %s",
+ self->priv->bus_address);
+ g_spawn_command_line_async (command, NULL);
+ g_free (command);
+
+ g_usleep (500 * 1000);
+ }
+
+ /* Cleanup */
+ g_io_channel_shutdown (channel, FALSE, &error);
+ g_assert_no_error (error);
+ g_io_channel_unref (channel);
+
+ /* Don't use g_file_delete since it calls into gvfs */
+ if (g_unlink (config_path) != 0)
+ g_assert_not_reached ();
+
+ g_free (config_path);
+ g_free (config_arg);
+}
+
+static void
+stop_daemon (FolksTestDBus *self)
+{
+#ifdef G_OS_WIN32
+ if (!TerminateProcess (self->priv->bus_pid, 0))
+ g_warning ("Can't terminate process: %s", g_win32_error_message (GetLastError()));
+#else
+ kill (self->priv->bus_pid, SIGTERM);
+#endif
+ _folks_test_watcher_remove_pid (self->priv->bus_pid);
+ g_spawn_close_pid (self->priv->bus_pid);
+ self->priv->bus_pid = 0;
+
+ g_free (self->priv->bus_address);
+ self->priv->bus_address = NULL;
+}
+
+static void
+common_envar_unset (void)
+{
+ /* Always want to unset the starter address since we don't support simulating
+ * auto-launched buses */
+ g_unsetenv ("DISPLAY");
+ g_unsetenv ("DBUS_SESSION_BUS_PID");
+ g_unsetenv ("DBUS_SESSION_BUS_WINDOWID");
+ g_unsetenv ("DBUS_STARTER_ADDRESS");
+ g_unsetenv ("DBUS_STARTER_BUS_TYPE");
+}
+
+static void
+partial_envar_unset (GBusType bus_type)
+{
+ common_envar_unset ();
+
+ switch (bus_type)
+ {
+ case G_BUS_TYPE_SESSION:
+ g_unsetenv ("DBUS_SESSION_BUS_ADDRESS");
+ break;
+ case G_BUS_TYPE_SYSTEM:
+ g_unsetenv ("DBUS_SYSTEM_BUS_ADDRESS");
+ break;
+ case G_BUS_TYPE_STARTER:
+ case G_BUS_TYPE_NONE:
+ default:
+ break;
+ }
+}
+
+/**
+ * folks_test_dbus_new:
+ * @flags: a #FolksTestDBusFlags
+ *
+ * Create a new #FolksTestDBus object.
+ *
+ * Returns: (transfer full): a new #FolksTestDBus.
+ */
+FolksTestDBus *
+folks_test_dbus_new (FolksTestDBusFlags flags)
+{
+ return g_object_new (FOLKS_TYPE_TEST_DBUS,
+ "flags", flags,
+ NULL);
+}
+
+/**
+ * folks_test_dbus_get_flags:
+ * @self: a #FolksTestDBus
+ *
+ * Get the flags of the #FolksTestDBus object.
+ *
+ * Returns: the value of #FolksTestDBus:flags property
+ */
+FolksTestDBusFlags
+folks_test_dbus_get_flags (FolksTestDBus *self)
+{
+ g_return_val_if_fail (FOLKS_IS_TEST_DBUS (self), FOLKS_TEST_DBUS_NONE);
+
+ return self->priv->flags;
+}
+
+/**
+ * folks_test_dbus_get_bus_address:
+ * @self: a #FolksTestDBus
+ *
+ * Get the address on which dbus-daemon is running. If folks_test_dbus_up() has not
+ * been called yet, %NULL is returned. This can be used with
+ * g_dbus_connection_new_for_address().
+ *
+ * Returns: (allow-none): the address of the bus, or %NULL.
+ */
+const gchar *
+folks_test_dbus_get_bus_address (FolksTestDBus *self)
+{
+ g_return_val_if_fail (FOLKS_IS_TEST_DBUS (self), NULL);
+
+ return self->priv->bus_address;
+}
+
+/**
+ * folks_test_dbus_add_service_dir:
+ * @self: a #FolksTestDBus
+ * @path: path to a directory containing .service files
+ *
+ * Add a path where dbus-daemon will look up .service files. This can't be
+ * called after folks_test_dbus_up().
+ */
+void
+folks_test_dbus_add_service_dir (FolksTestDBus *self,
+ const gchar *path)
+{
+ g_return_if_fail (FOLKS_IS_TEST_DBUS (self));
+ g_return_if_fail (self->priv->bus_address == NULL);
+
+ g_ptr_array_add (self->priv->service_dirs, g_strdup (path));
+}
+
+/**
+ * folks_test_dbus_up:
+ * @self: a #FolksTestDBus
+ *
+ * Start a dbus-daemon instance and set <envar>DBUS_SESSION_BUS_ADDRESS</envar>
+ * or <envar>DBUS_SYSTEM_BUS_ADDRESS</envar> (if the %FOLKS_TEST_DBUS_SYSTEM_BUS
+ * flag was passed to folks_test_dbus_new()). After this call, it is safe for
+ * unit tests to start sending messages on the session (or system) bus.
+ *
+ * If this function is called from the setup callback of g_test_add(),
+ * folks_test_dbus_down() must be called in its teardown callback.
+ *
+ * If this function is called from unit test's main(), then folks_test_dbus_down()
+ * must be called after g_test_run().
+ *
+ * As a side-effect, this function unsets the <envar>DISPLAY</envar>,
+ * <envar>DBUS_STARTER_BUS_ADDRESS</envar> and
+ * <envar>DBUS_STARTER_BUS_TYPE</envar> environment variables. It does not unset
+ * <envar>DBUS_SESSION_BUS_ADDRESS</envar> if a system bus is being spawned,
+ * and similarly for <envar>BUS_SYSTEM_BUS_ADDRESS</envar> with a session bus.
+ */
+void
+folks_test_dbus_up (FolksTestDBus *self)
+{
+ const gchar *envar;
+ GBusType bus_type;
+
+ g_return_if_fail (FOLKS_IS_TEST_DBUS (self));
+ g_return_if_fail (self->priv->bus_address == NULL);
+ g_return_if_fail (!self->priv->up);
+
+ start_daemon (self);
+
+ bus_type = (self->priv->flags & FOLKS_TEST_DBUS_SYSTEM_BUS) ?
+ G_BUS_TYPE_SYSTEM :
+ G_BUS_TYPE_SESSION;
+ partial_envar_unset (bus_type);
+
+ envar = (self->priv->flags & FOLKS_TEST_DBUS_SYSTEM_BUS) ?
+ "DBUS_SYSTEM_BUS_ADDRESS" :
+ "DBUS_SESSION_BUS_ADDRESS";
+ g_setenv (envar, self->priv->bus_address, TRUE);
+
+ self->priv->up = TRUE;
+}
+
+
+/**
+ * folks_test_dbus_stop:
+ * @self: a #FolksTestDBus
+ *
+ * Stop the session (or system) bus started by folks_test_dbus_up().
+ *
+ * Unlike folks_test_dbus_down(), this won't verify the #GDBusConnection
+ * singleton returned by g_bus_get() or g_bus_get_sync() is destroyed. Unit
+ * tests wanting to verify behaviour after the bus has been stopped
+ * can use this function but should still call folks_test_dbus_down() when done.
+ */
+void
+folks_test_dbus_stop (FolksTestDBus *self)
+{
+ g_return_if_fail (FOLKS_IS_TEST_DBUS (self));
+ g_return_if_fail (self->priv->bus_address != NULL);
+
+ stop_daemon (self);
+}
+
+/**
+ * folks_test_dbus_down:
+ * @self: a #FolksTestDBus
+ *
+ * Stop the session (or system) bus started by folks_test_dbus_up().
+ *
+ * This will wait for the singleton returned by g_bus_get() or g_bus_get_sync()
+ * is destroyed. This is done to ensure that the next unit test won't get a
+ * leaked singleton from this test.
+ *
+ * As a side-effect, this function unsets the <envar>DISPLAY</envar>,
+ * <envar>DBUS_STARTER_BUS_ADDRESS</envar> and
+ * <envar>DBUS_STARTER_BUS_TYPE</envar> environment variables. It does not unset
+ * <envar>DBUS_SESSION_BUS_ADDRESS</envar> if a system bus is being shut down,
+ * and similarly for <envar>BUS_SYSTEM_BUS_ADDRESS</envar> with a session bus.
+ */
+void
+folks_test_dbus_down (FolksTestDBus *self)
+{
+ GBusType bus_type;
+ GDBusConnection *connection;
+
+ g_return_if_fail (FOLKS_IS_TEST_DBUS (self));
+ g_return_if_fail (self->priv->up);
+
+ bus_type = (self->priv->flags & FOLKS_TEST_DBUS_SYSTEM_BUS) ?
+ G_BUS_TYPE_SYSTEM :
+ G_BUS_TYPE_SESSION;
+
+ connection = g_bus_get_sync (bus_type, NULL, NULL);
+ if (connection != NULL)
+ g_dbus_connection_set_exit_on_close (connection, FALSE);
+
+ if (self->priv->bus_address != NULL)
+ stop_daemon (self);
+
+ if (connection != NULL)
+ _g_object_dispose_and_wait_weak_notify (connection);
+
+ partial_envar_unset (bus_type);
+ self->priv->up = FALSE;
+}
+
+/**
+ * folks_test_dbus_unset:
+ *
+ * Unset various D-Bus environment variables to ensure the test won't use the
+ * user's session (or system) bus:
+ * <itemizedlist>
+ * <listitem><para>DISPLAY</para></listitem>
+ * <listitem><para>DBUS_SESSION_BUS_ADDRESS</para></listitem>
+ * <listitem><para>DBUS_SESSION_BUS_PID</para></listitem>
+ * <listitem><para>DBUS_SESSION_BUS_WINDOWID</para></listitem>
+ * <listitem><para>DBUS_SYSTEM_BUS_ADDRESS</para></listitem>
+ * <listitem><para>DBUS_STARTER_ADDRESS</para></listitem>
+ * <listitem><para>DBUS_STARTER_BUS_TYPE</para></listitem>
+ * </itemizedlist>
+ *
+ * This is useful for unit tests that want to verify behaviour when no session
+ * (or system) bus is running. It is not necessary to call this if the unit test
+ * already calls folks_test_dbus_up() before acquiring the bus.
+ */
+void
+folks_test_dbus_unset (void)
+{
+ /* See also: partial_envar_unset(). */
+ common_envar_unset ();
+
+ g_unsetenv ("DBUS_SESSION_BUS_ADDRESS");
+ g_unsetenv ("DBUS_SYSTEM_BUS_ADDRESS");
+}
diff --git a/tests/lib/gtestdbus.h b/tests/lib/gtestdbus.h
new file mode 100644
index 00000000..2c726db7
--- /dev/null
+++ b/tests/lib/gtestdbus.h
@@ -0,0 +1,90 @@
+/* GIO testing utilities
+ *
+ * Copyright (C) 2008-2010 Red Hat, Inc.
+ * Copyright (C) 2012 Collabora Ltd. <http://www.collabora.co.uk/>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: David Zeuthen <davidz@redhat.com>
+ * Xavier Claessens <xavier.claessens@collabora.co.uk>
+ */
+
+#ifndef __FOLKS_TEST_DBUS_H__
+#define __FOLKS_TEST_DBUS_H__
+
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+/**
+ * FolksTestDBusFlags:
+ * @FOLKS_TEST_DBUS_NONE: No flags.
+ * @FOLKS_TEST_DBUS_SESSION_BUS: Create a session bus (the default).
+ * @FOLKS_TEST_DBUS_SYSTEM_BUS: Create a system bus instead of a session bus.
+ *
+ * Flags to define #FolksTestDBus behaviour.
+ *
+ * Since: 2.34
+ */
+typedef enum /*< flags >*/ {
+ FOLKS_TEST_DBUS_NONE = 0,
+ FOLKS_TEST_DBUS_SESSION_BUS = 0, /* default; same as NONE */
+ FOLKS_TEST_DBUS_SYSTEM_BUS = 1 << 0,
+} FolksTestDBusFlags;
+
+#define FOLKS_TYPE_TEST_DBUS_FLAGS (folks_test_dbus_flags_get_type ())
+GType folks_test_dbus_flags_get_type (void) G_GNUC_CONST;
+
+typedef struct _FolksTestDBus FolksTestDBus;
+
+
+#define FOLKS_TYPE_TEST_DBUS \
+ (folks_test_dbus_get_type ())
+#define FOLKS_TEST_DBUS(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), FOLKS_TYPE_TEST_DBUS, \
+ FolksTestDBus))
+#define FOLKS_IS_TEST_DBUS(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), FOLKS_TYPE_TEST_DBUS))
+
+GLIB_AVAILABLE_IN_2_34
+GType folks_test_dbus_get_type (void) G_GNUC_CONST;
+
+GLIB_AVAILABLE_IN_2_34
+FolksTestDBus * folks_test_dbus_new (FolksTestDBusFlags flags);
+
+GLIB_AVAILABLE_IN_2_34
+FolksTestDBusFlags folks_test_dbus_get_flags (FolksTestDBus *self);
+
+GLIB_AVAILABLE_IN_2_34
+const gchar * folks_test_dbus_get_bus_address (FolksTestDBus *self);
+
+GLIB_AVAILABLE_IN_2_34
+void folks_test_dbus_add_service_dir (FolksTestDBus *self,
+ const gchar *path);
+
+GLIB_AVAILABLE_IN_2_34
+void folks_test_dbus_up (FolksTestDBus *self);
+
+GLIB_AVAILABLE_IN_2_34
+void folks_test_dbus_stop (FolksTestDBus *self);
+
+GLIB_AVAILABLE_IN_2_34
+void folks_test_dbus_down (FolksTestDBus *self);
+
+GLIB_AVAILABLE_IN_2_34
+void folks_test_dbus_unset (void);
+
+G_END_DECLS
+
+#endif /* __FOLKS_TEST_DBUS_H__ */
diff --git a/tests/lib/key-file/Makefile.am b/tests/lib/key-file/Makefile.am
index ebb067ba..a909d78a 100644
--- a/tests/lib/key-file/Makefile.am
+++ b/tests/lib/key-file/Makefile.am
@@ -14,6 +14,7 @@ libkf_test_la_VALAFLAGS = \
--vapidir=$(abs_top_srcdir)/tests/lib \
--vapidir=$(abs_top_builddir)/tests/lib \
--pkg folks-test \
+ --pkg folks-test-dbus \
-g \
$(NULL)
diff --git a/tests/lib/libsocialweb/Makefile.am b/tests/lib/libsocialweb/Makefile.am
index f186fe54..252813d7 100644
--- a/tests/lib/libsocialweb/Makefile.am
+++ b/tests/lib/libsocialweb/Makefile.am
@@ -19,6 +19,7 @@ libsocialweb_test_la_VALAFLAGS = \
--pkg libsocialweb-client \
--pkg folks-libsocialweb \
--pkg folks-test \
+ --pkg folks-test-dbus \
-g \
$(NULL)
diff --git a/tests/lib/org-freedesktop-dbus-mock.vala b/tests/lib/org-freedesktop-dbus-mock.vala
new file mode 100644
index 00000000..386477f0
--- /dev/null
+++ b/tests/lib/org-freedesktop-dbus-mock.vala
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2013 Collabora Ltd.
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Philip Withnall <philip.withnall@collabora.co.uk>
+ */
+
+using GLib;
+
+/**
+ * Vala wrapper for the standard org.freedesktop.DBus.Mock interface.
+ *
+ * This is exposed by python-dbusmock as the primary means of controlling a
+ * mocked up D-Bus service.
+ *
+ * @since UNRELEASED
+ */
+
+/* Reference:
+ * http://bazaar.launchpad.net/~pitti/python-dbusmock/trunk/view/head:/README.rst */
+namespace org
+ {
+ namespace freedesktop
+ {
+ namespace DBus
+ {
+ [DBus (name = "org.freedesktop.DBus.Mock")]
+ public interface Mock : Object
+ {
+ /* Signals. */
+ [DBus (name = "MethodCalled")]
+ public abstract signal void method_called (string method_name,
+ Variant[] args);
+
+ /* Methods. */
+ [DBus (name = "AddMethod")]
+ public abstract void add_method (string interface_name,
+ string name, string in_sig, string out_sig, string code)
+ throws IOError;
+
+ /* Parameter to AddMethods(). */
+ public struct Method
+ {
+ public string name;
+ public string in_sig;
+ public string out_sig;
+ }
+
+ [DBus (name = "AddMethods")]
+ public abstract void add_methods (string interface_name,
+ Method[] methods) throws IOError;
+
+ [DBus (name = "AddObject")]
+ public abstract void add_object (string path,
+ string interface_name,
+ HashTable<string, Variant> properties, Method[] methods)
+ throws IOError;
+
+ [DBus (name = "AddProperties")]
+ public abstract void add_properties (string interface_name,
+ HashTable<string, Variant> properties) throws IOError;
+
+ [DBus (name = "AddProperty")]
+ public abstract void add_property (string interface_name,
+ string name, Variant val) throws IOError;
+
+ [DBus (name = "AddTemplate")]
+ public abstract void add_template (string template_name,
+ HashTable<string, Variant> template_params)
+ throws IOError;
+
+ [DBus (name = "ClearCalls")]
+ public abstract void clear_calls () throws IOError;
+
+ [DBus (name = "EmitSignal")]
+ public abstract void emit_signal (string interface_name,
+ string name, string signature, Variant[] args)
+ throws IOError;
+
+ /* Returned by GetCalls(). */
+ public struct Call
+ {
+ public uint64 call_time;
+ public string method_name;
+ public Variant[] args;
+ }
+
+ [DBus (name = "GetCalls")]
+ public abstract Call[] get_calls () throws IOError;
+
+ /* Returned by GetMethodCalls(). */
+ public struct MethodCall
+ {
+ public uint64 call_time;
+ public Variant[] args;
+ }
+
+ [DBus (name = "GetMethodCalls")]
+ public abstract MethodCall[] get_method_calls (string method)
+ throws IOError;
+
+ [DBus (name = "RemoveObject")]
+ public abstract void remove_object (string path)
+ throws IOError;
+
+ [DBus (name = "Reset")]
+ public abstract void reset () throws IOError;
+ }
+ }
+ }
+ }
diff --git a/tests/lib/telepathy/Makefile.am b/tests/lib/telepathy/Makefile.am
index 159073b0..648249e2 100644
--- a/tests/lib/telepathy/Makefile.am
+++ b/tests/lib/telepathy/Makefile.am
@@ -21,7 +21,9 @@ libtpf_test_la_VALAFLAGS = \
--vapidir=$(abs_top_builddir)/tests/lib \
--vapidir=$(abs_top_srcdir)/tests/lib/key-file \
--vapidir=$(abs_top_builddir)/tests/lib/key-file \
+ --pkg build-conf \
--pkg folks-test \
+ --pkg folks-test-dbus \
--pkg kf-test \
--pkg tp-test-contactlist \
-g \
@@ -33,7 +35,14 @@ libtpf_test_la_SOURCES = \
libtpf_test_la_CPPFLAGS = \
$(AM_CPPFLAGS) \
+ -I$(top_srcdir) \
+ -I$(top_srcdir)/folks \
+ -include $(CONFIG_HEADER) \
-include $(top_srcdir)/folks/warnings.h \
+ -DABS_TOP_SRCDIR=\"${abs_top_srcdir}\" \
+ -DABS_TOP_BUILDDIR=\"${abs_top_builddir}\" \
+ -DPKGLIBEXECDIR=\"${pkglibexecdir}\" \
+ -DPACKAGE_DATADIR=\"${pkgdatadir}\" \
$(NULL)
libtpf_test_la_CFLAGS = \
diff --git a/tests/lib/telepathy/test-case.vala b/tests/lib/telepathy/test-case.vala
index 54343c76..28ff908d 100644
--- a/tests/lib/telepathy/test-case.vala
+++ b/tests/lib/telepathy/test-case.vala
@@ -129,6 +129,11 @@ public class TpfTest.TestCase : Folks.TestCase
*/
public virtual void create_kf_backend ()
{
+ /* Default key-file backend file to load. */
+ Environment.set_variable ("FOLKS_BACKEND_KEY_FILE_PATH",
+ Folks.BuildConf.ABS_TOP_SRCDIR + "/data/relationships-empty.ini",
+ true);
+
if (use_keyfile_too)
this.kf_backend = new KfTest.Backend ();
}
diff --git a/tests/lib/test-case.vala b/tests/lib/test-case.vala
index a174f647..febc251e 100644
--- a/tests/lib/test-case.vala
+++ b/tests/lib/test-case.vala
@@ -41,6 +41,13 @@ public abstract class Folks.TestCase : Object
{
Intl.setlocale (LocaleCategory.ALL, "");
+ /* Enable all debug output from libfolks. This is OK, as automake-1.12’s
+ * parallel test harness will only save the debug output from failed
+ * tests. If the user’s already set those variables, though, don’t
+ * overwrite them. */
+ Environment.set_variable ("G_MESSAGES_DEBUG", "all", false);
+ Environment.set_variable ("FOLKS_DEBUG", "all", false);
+
/* Turn off use of gvfs. If using GTestDBus it's unavailable,
* and if not it's pointless: all we need is the local filesystem. */
Environment.set_variable ("GIO_USE_VFS", "local", true);
@@ -79,6 +86,9 @@ public abstract class Folks.TestCase : Object
if (Folks.BuildConf.HAVE_TRACKER)
locations += Folks.BuildConf.ABS_TOP_BUILDDIR + "/backends/tracker/.libs/tracker.so";
+ if (Folks.BuildConf.HAVE_BLUEZ)
+ locations += Folks.BuildConf.ABS_TOP_BUILDDIR + "/backends/bluez/.libs/bluez.so";
+
Environment.set_variable ("FOLKS_BACKEND_PATH",
string.joinv (":", locations), true);
}
@@ -113,12 +123,8 @@ public abstract class Folks.TestCase : Object
*
* Subclasses may override this method to do additional setup
* (create more subdirectories or set more environment variables).
- *
- * FIXME: Subclasses relying on being called by with-session-bus-*.sh
- * may override this method to return null, although we should really
- * stop doing that.
*/
- public virtual string? create_transient_dir ()
+ public virtual string create_transient_dir ()
{
unowned string tmp = Environment.get_tmp_dir ();
string transient = "%s/folks-test.XXXXXX".printf (tmp);
@@ -167,6 +173,19 @@ public abstract class Folks.TestCase : Object
error ("unable to create '%s': %s",
runtime, GLib.strerror (GLib.errno));
+ /* Directories to contain D-Bus service files. */
+ var dbus_system = "%s/dbus-1/system-services".printf (transient);
+
+ if (GLib.DirUtils.create_with_parents (dbus_system, 0700) != 0)
+ error ("unable to create '%s': %s",
+ local, GLib.strerror (GLib.errno));
+
+ var dbus_session = "%s/dbus-1/services".printf (transient);
+
+ if (GLib.DirUtils.create_with_parents (dbus_session, 0700) != 0)
+ error ("unable to create '%s': %s",
+ local, GLib.strerror (GLib.errno));
+
/* Unset some things we don't want to inherit. In particular,
* Tracker might try to index XDG_*_DIR, which we don't want. */
Environment.unset_variable ("XDG_DESKTOP_DIR");
@@ -182,6 +201,87 @@ public abstract class Folks.TestCase : Object
}
/**
+ * Create a D-Bus service file for a python-dbusmock service.
+ *
+ * Create a service file to allow auto-launching a python-dbusmock service
+ * which uses the given ``dbusmock_template_name`` to mock up the service
+ * running at ``bus_name`` on the ``bus_type`` bus (which must either be
+ * {@link BusType.SYSTEM} or {@link BusType.SESSION}.
+ *
+ * This requires Python 3 to be installed and available to run as ``python3``
+ * somewhere in the system ``PATH``.
+ *
+ * It will create a temporary log file which python-dbusmock will log to if
+ * launched. The name of the log file will be printed to the test logs.
+ *
+ * The D-Bus service file itself will be created in a subdirectory of
+ * {@link TestCase.transient_dir}, which the {@link TestDBus} instance has
+ * already been configured to use as a service directory. This requires
+ * {@link TestCase.create_transient_dir} to have been called already.
+ *
+ * @param bus_type the bus the service should be auto-launchable from
+ * @param bus_name the well-known bus name used by the service
+ * @param dbusmock_template_name name of the python-dbusmock template to use
+ *
+ * @since UNRELEASED
+ */
+ public void create_dbusmock_service (BusType bus_type, string bus_name,
+ string dbusmock_template_name)
+ {
+ string service_dir;
+ switch (bus_type)
+ {
+ case BusType.SYSTEM:
+ service_dir = "system-services";
+ break;
+ case BusType.SESSION:
+ service_dir = "services";
+ break;
+ case BusType.STARTER:
+ case BusType.NONE:
+ default:
+ assert_not_reached ();
+ }
+
+ /* Find where the Python 3 executable is (service files require absolute
+ * paths). */
+ var python = Environment.find_program_in_path ("python3");
+ if (python == null)
+ {
+ error ("Couldn’t find `python3` in $PATH; can’t run " +
+ "python-dbusmock.");
+ }
+
+ /* Create a temporary log file for dbusmock to use. This doesn’t need to
+ * use mkstemp() because it’s already in a unique temporary directory. */
+ var log_file_name =
+ Path.build_filename (this.transient_dir,
+ "dbusmock-%s-%s-%s.log".printf (service_dir, bus_name,
+ dbusmock_template_name));
+ Test.message ("python-dbusmock service ‘%s’ (template ‘%s’) will log " +
+ "to ‘%s’.", bus_name, dbusmock_template_name, log_file_name);
+
+ /* Write out the service file for the dbusmock service. */
+ var service_file_name =
+ Path.build_filename (this.transient_dir, "dbus-1", service_dir,
+ dbusmock_template_name + ".service");
+ var service_file = ("[D-BUS Service]\n" +
+ "Name=%s\n" +
+ "Exec=%s -m dbusmock --template %s -l %s\n").printf (bus_name, python,
+ dbusmock_template_name, log_file_name);
+
+ try
+ {
+ FileUtils.set_contents (service_file_name, service_file);
+ }
+ catch (FileError e2)
+ {
+ error ("Error creating D-Bus service file ‘%s’: %s",
+ service_file_name, e2.message);
+ }
+ }
+
+ /**
* A private D-Bus session, normally created by private_bus_up()
* from the constructor.
*
@@ -189,7 +289,17 @@ public abstract class Folks.TestCase : Object
* address is frequently treated as process-global (for instance,
* libdbus will cache a single session bus connection indefinitely).
*/
- public GLib.TestDBus? test_dbus = null;
+ public Folks.TestDBus? test_dbus = null;
+
+ /**
+ * A private D-Bus system bus, normally created by private_bus_up() from the
+ * constructor.
+ *
+ * As with {@link TestCase.test_dbus} this is per-process.
+ *
+ * @since UNRELEASED
+ */
+ public Folks.TestDBus? test_system_dbus = null;
/**
* If true, libraries involved in this test use dbus-1 (or dbus-glib-1)
@@ -211,18 +321,40 @@ public abstract class Folks.TestCase : Object
*
* This is per-process, not per-test, for the reasons mentioned for
* //test_dbus//.
+ *
+ * By calling {@link TestCase.create_dbusmock_service} in an overridden
+ * version of this method, python-dbusmock services may be set up.
*/
public virtual void private_bus_up ()
{
- Environment.unset_variable ("DBUS_SESSION_BUS_ADDRESS");
- Environment.unset_variable ("DBUS_SESSION_BUS_PID");
+ /* Clear out existing bus variables. */
+ Folks.TestDBus.unset ();
+
+ /* Set up the system bus first, then shimmy its address sideways. */
+ this.test_system_dbus = new Folks.TestDBus (Folks.TestDBusFlags.SYSTEM_BUS);
+ var test_system_dbus = (!) this.test_system_dbus;
+ test_system_dbus.add_service_dir (
+ this.transient_dir + "/dbus-1/system-services");
- this.test_dbus = new GLib.TestDBus (GLib.TestDBusFlags.NONE);
+ test_system_dbus.up ();
+
+ var system_bus_address = test_system_dbus.get_bus_address ();
+
+ /* Now the session bus. */
+ this.test_dbus = new Folks.TestDBus (Folks.TestDBusFlags.NONE);
var test_dbus = (!) this.test_dbus;
+ test_dbus.add_service_dir (this.transient_dir + "/dbus-1/services");
test_dbus.up ();
- assert (Environment.get_variable ("DBUS_SESSION_BUS_ADDRESS") != null);
+ var session_bus_address = test_dbus.get_bus_address ();
+
+ /* Set the bus addresses. We have to do this manually to prevent GTestDBus
+ * from unsetting the first bus’ address when starting the second. */
+ Environment.set_variable ("DBUS_SYSTEM_BUS_ADDRESS", system_bus_address,
+ true);
+ Environment.set_variable ("DBUS_SESSION_BUS_ADDRESS", session_bus_address,
+ true);
/* Tell subprocesses that we're running in a private D-Bus
* session, so certain operations that would otherwise be dangerous
@@ -290,6 +422,12 @@ public abstract class Folks.TestCase : Object
this.test_dbus = null;
}
+ if (this.test_system_dbus != null)
+ {
+ ((!) this.test_system_dbus).down ();
+ this.test_system_dbus = null;
+ }
+
if (this._transient_dir != null)
{
unowned string dir = (!) this._transient_dir;
diff --git a/tests/lib/test-utils.vala b/tests/lib/test-utils.vala
index cbdc4192..67f12481 100644
--- a/tests/lib/test-utils.vala
+++ b/tests/lib/test-utils.vala
@@ -342,6 +342,98 @@ public class Folks.TestUtils
}
/**
+ * Wait for the given personas to be added to or removed from an aggregator.
+ *
+ * This will yield until all of the personas listed in
+ * ``expected_added_persona_names`` are added to the aggregator; or until all
+ * of the personas listed in ``expected_removed_persona_names`` are removed
+ * from it. Only one of the two arrays may be non-empty; this method does not
+ * currently implement checking of complex individual change notifications.
+ *
+ * No timeout is used, so if the aggregator never adds or removes all the
+ * expected personas, this function will never return; callers must add their
+ * own timeout to avoid this if necessary. On return from this function, all
+ * of the given names are guaranteed to exist in the aggregator.
+ *
+ * The names in ``expected_added_persona_names`` and
+ * ``expected_removed_persona_names`` must be those appearing in the
+ * {@link NameDetails.full_name} property of the personas (and hence of the
+ * individuals).
+ *
+ * @param aggregator the aggregator to check
+ * @param expected_added_persona_names set of full names of the expected
+ * personas to be added
+ * @param expected_removed_persona_names set of full names of the expected
+ * personas to be removed
+ *
+ * @since UNRELEASED
+ */
+ public static async void aggregator_wait_for_individuals (
+ IndividualAggregator aggregator, string[] expected_added_persona_names,
+ string[] expected_removed_persona_names)
+ {
+ /* Currently only support waiting for all additions or all removals. */
+ assert (expected_added_persona_names.length == 0 ||
+ expected_removed_persona_names.length == 0);
+
+ var expected_added = new HashSet<string> ();
+ var expected_removed = new HashSet<string> ();
+
+ foreach (var name in expected_added_persona_names)
+ expected_added.add (name);
+ foreach (var name in expected_removed_persona_names)
+ expected_removed.add (name);
+
+ /* Set up the aggregator */
+ var signal_id = aggregator.individuals_changed_detailed.connect (
+ (changes) =>
+ {
+ var added = changes.get_values ();
+ var removed = changes.get_keys ();
+
+ foreach (Individual i in added)
+ {
+ if (expected_added.size == 0)
+ {
+ assert (i == null);
+ break;
+ }
+
+ assert (i != null);
+
+ var name_details = i as NameDetails;
+ assert (name_details != null);
+ expected_added.remove (name_details.full_name);
+ }
+
+ foreach (var i in removed)
+ {
+ if (expected_removed.size == 0)
+ {
+ assert (i == null);
+ break;
+ }
+
+ assert (i != null);
+
+ var name_details = i as NameDetails;
+ assert (name_details != null);
+ expected_removed.remove (name_details.full_name);
+ }
+
+
+ /* Finished? */
+ if (expected_added.size == 0 && expected_removed.size == 0)
+ TestUtils.aggregator_wait_for_individuals.callback ();
+ });
+
+ yield;
+
+ aggregator.disconnect (signal_id);
+ assert (expected_added.size == 0 && expected_removed.size == 0);
+ }
+
+ /**
* Synchronously prepare an aggregator and wait for the given personas to be
* added to it.
*
diff --git a/tests/lib/tracker/Makefile.am b/tests/lib/tracker/Makefile.am
index 02a4c5a5..639efb2e 100644
--- a/tests/lib/tracker/Makefile.am
+++ b/tests/lib/tracker/Makefile.am
@@ -19,6 +19,7 @@ libtracker_test_la_VALAFLAGS = \
--pkg tracker-sparql-$(TRACKER_SPARQL_MAJOR) \
--pkg folks-tracker \
--pkg folks-test \
+ --pkg folks-test-dbus \
-g \
$(NULL)
diff --git a/tests/lib/tracker/test-case.vala b/tests/lib/tracker/test-case.vala
index 3a1acd37..fd0df80b 100644
--- a/tests/lib/tracker/test-case.vala
+++ b/tests/lib/tracker/test-case.vala
@@ -26,8 +26,8 @@
* Folks is configured to use the Tracker backend as primary store,
* and no other backends.
*
- * FIXME: For now, this relies on running under with-session-bus-tracker.sh
- * with FOLKS_BACKEND_PATH set.
+ * This uses tracker-control to start and stop Tracker services on a private
+ * D-Bus bus.
*/
public class TrackerTest.TestCase : Folks.TestCase
{
@@ -47,14 +47,6 @@ public class TrackerTest.TestCase : Folks.TestCase
*/
public TestCase (string name)
{
- /* This variable is set in the same place as the various variables we
- * care about for sandboxing purposes, like XDG_CONFIG_HOME and
- * DBUS_SESSION_BUS_ADDRESS. */
- if (Environment.get_variable ("FOLKS_TESTS_SANDBOXED_DBUS")
- != "tracker")
- error ("Tracker tests must be run in a private D-Bus session " +
- "with Tracker services");
-
base (name);
Environment.set_variable ("FOLKS_BACKENDS_ALLOWED", "tracker", true);
@@ -63,17 +55,53 @@ public class TrackerTest.TestCase : Folks.TestCase
this.tracker_backend = new TrackerTest.Backend ();
}
- public override string? create_transient_dir ()
- {
- /* Don't do anything. We're currently relying on
- * being wrapped in with-session-bus-tracker.sh. */
- return null;
- }
-
public override void private_bus_up ()
{
- /* Don't do anything. We're currently relying on
- * being wrapped in with-session-bus-tracker.sh. */
+ base.private_bus_up ();
+
+ /* Find out the libexec directory to use. */
+ int exit_status = -1;
+ string capture_stdout = null;
+
+ try
+ {
+ Process.spawn_sync (null /* cwd */,
+ { "pkg-config", "--variable=prefix", "tracker-miner-1.0" },
+ null /* envp */,
+ SpawnFlags.SEARCH_PATH /* flags */,
+ null /* child setup */,
+ out capture_stdout,
+ null /* do not capture stderr */,
+ out exit_status);
+
+ Process.check_exit_status (exit_status);
+ }
+ catch (GLib.Error e1)
+ {
+ error ("Error getting libexecdir from pkg-config: %s", e1.message);
+ }
+
+ /* FIXME: There really should be a libexec variable in the pkg-config
+ * file. */
+ var libexec = capture_stdout.strip () + "/libexec";
+
+ /* Create service files for the Tracker binaries. */
+ var service_file_name =
+ Path.build_filename (this.transient_dir, "dbus-1", "services",
+ "org.freedesktop.Tracker1.service");
+ var service_file = ("[D-BUS Service]\n" +
+ "Name=org.freedesktop.Tracker1\n" +
+ "Exec=%s/tracker-store\n").printf (libexec);
+
+ try
+ {
+ FileUtils.set_contents (service_file_name, service_file);
+ }
+ catch (FileError e2)
+ {
+ error ("Error creating D-Bus service file ‘%s’: %s",
+ service_file_name, e2.message);
+ }
}
public override void tear_down ()
diff --git a/tests/libsocialweb/Makefile.am b/tests/libsocialweb/Makefile.am
index 02df9eb5..f84c02c1 100644
--- a/tests/libsocialweb/Makefile.am
+++ b/tests/libsocialweb/Makefile.am
@@ -36,10 +36,6 @@ noinst_PROGRAMS = \
aggregation \
$(NULL)
-TESTS_ENVIRONMENT = \
- $(top_srcdir)/tests/tools/execute-test.sh \
- $(NULL)
-
TESTS = $(noinst_PROGRAMS)
dummy_lsw_SOURCES = \
diff --git a/tests/telepathy/Makefile.am b/tests/telepathy/Makefile.am
index 645fdcee..b65efd5f 100644
--- a/tests/telepathy/Makefile.am
+++ b/tests/telepathy/Makefile.am
@@ -43,11 +43,6 @@ LDADD = \
-L$(top_srcdir)/backends/telepathy/lib \
$(NULL)
-TESTS_ENVIRONMENT = \
- FOLKS_BACKEND_KEY_FILE_PATH=$(srcdir)/data/relationships-empty.ini \
- $(top_srcdir)/tests/tools/execute-test.sh \
- $(NULL)
-
TESTS = \
persona-store-capabilities \
individual-retrieval \
diff --git a/tests/test.mk b/tests/test.mk
index 0e0eb6bb..801d17ba 100644
--- a/tests/test.mk
+++ b/tests/test.mk
@@ -31,6 +31,7 @@ test_valaflags = \
--vapidir=$(top_builddir)/backends/dummy/lib \
--pkg folks \
--pkg folks-test \
+ --pkg folks-test-dbus \
--pkg folks-dummy \
--pkg gee-0.8 \
--pkg gio-2.0 \
diff --git a/tests/tools/Makefile.am b/tests/tools/Makefile.am
index e98f35b0..542e5a28 100644
--- a/tests/tools/Makefile.am
+++ b/tests/tools/Makefile.am
@@ -1,12 +1,5 @@
EXTRA_DIST = \
- eds.sh \
- execute-test.sh \
- with-session-bus.sh \
- dbus-session.sh \
manager-file.py \
- with-session-bus-eds.sh \
- with-session-bus-tracker.sh \
- tracker.sh \
$(NULL)
-include $(top_srcdir)/git.mk
diff --git a/tests/tools/dbus-session.sh b/tests/tools/dbus-session.sh
deleted file mode 100644
index 35c09d40..00000000
--- a/tests/tools/dbus-session.sh
+++ /dev/null
@@ -1,119 +0,0 @@
-#
-# Helper functions to start your own D-Bus session.
-#
-# Refactored from with-session-bush.sh (from telepathy-glib).
-#
-# The canonical location of this program is the telepathy-glib tools/
-# directory, please synchronize any changes with that copy.
-#
-# Copyright (C) 2007-2008,2011 Collabora Ltd. <http://www.collabora.co.uk/>
-#
-# Copying and distribution of this file, with or without modification,
-# are permitted in any medium without royalty provided the copyright
-# notice and this notice are preserved.
-
-
-dbus_daemon_args="--print-address=5 --print-pid=6 --fork"
-dbus_verbose=0
-dbus_me=with-session-bus
-dbus_sleep=0
-dbus_with_session=""
-dbus_config_file=""
-
-# Params:
-# verbose: 0 for off and 1 for on
-#
-dbus_init () {
- unset DBUS_SESSION_BUS_ADDRESS
- unset DBUS_SESSION_BUS_PID
- unset DBUS_STARTER_ADDRESS
- unset DBUS_STARTER_BUS_TYPE
-
- exec 5> $dbus_me-$$.address
- exec 6> $dbus_me-$$.pid
- dbus_verbose=$1
-}
-
-dbus_usage ()
-{
- echo "usage: $me [options] -- program [program_options]" >&2
- echo "Requires write access to the current directory." >&2
- echo "" >&2
- echo "If \$WITH_SESSION_BUS_FORK_DBUS_MONITOR is set, fork dbus-monitor" >&2
- echo "with the arguments in \$WITH_SESSION_BUS_FORK_DBUS_MONITOR_OPT." >&2
- echo "The output of dbus-monitor is saved in $me-<pid>.dbus-monitor-logs" >&2
- exit 2
-}
-
-dbus_parse_args () {
- while test "z$1" != "z--"; do
- case "$1" in
- --sleep=*)
- sleep="$1"
- dbus_sleep="${sleep#--sleep=}"
- shift
- ;;
- --session)
- dbus_with_session="--session"
- shift
- ;;
- --config-file=*)
- # FIXME: assumes config file doesn't contain any special characters
- dbus_config_file="$1"
- shift
- ;;
- *)
- dbus_usage
- ;;
- esac
- done
-}
-
-dbus_start () {
- local args="$dbus_daemon_args $dbus_with_session $dbus_config_file "
-
- if [ $dbus_verbose -gt 0 ] ; then
- echo -n "dbus args $args "
- fi
-
- dbus-daemon $args
-
- {
- if [ $dbus_verbose -gt 0 ] ; then
- echo -n "Temporary bus daemon is "; cat $dbus_me-$$.address;
- fi
- } >&2
-
- {
- if [ $dbus_verbose -gt 0 ] ; then
- echo -n "Temporary bus daemon PID is "; head -n1 $dbus_me-$$.pid;
- fi
- } >&2
-
- DBUS_SESSION_BUS_ADDRESS="`cat $dbus_me-$$.address`"
- export DBUS_SESSION_BUS_ADDRESS
-
- if [ -n "$WITH_SESSION_BUS_FORK_DBUS_MONITOR" ] ; then
- if [ $dbus_verbose -gt 0 ] ; then
- echo -n "Forking dbus-monitor " \
- "$WITH_SESSION_BUS_FORK_DBUS_MONITOR_OPT" >&2
- fi
- dbus-monitor $WITH_SESSION_BUS_FORK_DBUS_MONITOR_OPT \
- > $dbus_me-$$.dbus-monitor-logs 2>&1 &
- fi
-}
-
-#
-# This should be called for INT, HUP and TERM signals
-#
-dbus_stop () {
- pid=`head -n1 $dbus_me-$$.pid`
- if test -n "$pid" ; then
- if [ $dbus_verbose -gt 0 ] ; then
- echo "Killing temporary bus daemon: $pid" >&2
- fi
- kill -INT "$pid"
- fi
- rm -f $dbus_me-$$.address
- rm -f $dbus_me-$$.pid
-}
diff --git a/tests/tools/eds.sh b/tests/tools/eds.sh
deleted file mode 100644
index e4821446..00000000
--- a/tests/tools/eds.sh
+++ /dev/null
@@ -1,35 +0,0 @@
-#
-# Helper functions to start your own e-d-s instance. This depends
-# on you having your own D-Bus session bus started (first).
-#
-#
-# Copyright (C) 2011 Collabora Ltd. <http://www.collabora.co.uk/>
-#
-# Copying and distribution of this file, with or without modification,
-# are permitted in any medium without royalty provided the copyright
-# notice and this notice are preserved.
-
-eds_tmpdir=$(mktemp -d)
-libexec=$(pkg-config --variable=libexecdir libedata-book-1.2)
-
-cur_dir=`dirname $0`
-
-eds_init_settings () {
- export XDG_DATA_HOME=$eds_tmpdir/.local
- export XDG_CACHE_HOME=$eds_tmpdir/.cache
- export XDG_CONFIG_HOME=$eds_tmpdir/.config
- mkdir -p $XDG_CONFIG_HOME/evolution/sources
-}
-
-eds_start () {
- $libexec/evolution-source-registry > /dev/null 2>&1 &
- $libexec/evolution-addressbook-factory --wait-for-client > /dev/null 2>&1 &
- sleep 2
-}
-
-# This should be called on INT TERM and EXIT
-eds_stop () {
- rm -rf $eds_tmpdir
- rm -rf $eds_tmpdir
-}
-
diff --git a/tests/tools/execute-test.sh b/tests/tools/execute-test.sh
deleted file mode 100755
index 54b4e33d..00000000
--- a/tests/tools/execute-test.sh
+++ /dev/null
@@ -1,30 +0,0 @@
-#!/bin/sh
-# with-session-bus.sh - run a program with a temporary D-Bus session daemon
-#
-# interesting bits have been move into dbus to permit reusability
-#
-# Copyright (C) 2007-2008 Collabora Ltd. <http://www.collabora.co.uk/>
-#
-# Copying and distribution of this file, with or without modification,
-# are permitted in any medium without royalty provided the copyright
-# notice and this notice are preserved.
-
-e=0
-
-if test -t 1 && test "z$CHECK_VERBOSE" != z; then
- "$@" || e=$?
-else
- "$@" > capture-$$.log 2>&1 || e=$?
-fi
-
-# if exit code is 0, check for skipped tests
-if test z$e = z0; then
- if test -f capture-$$.log; then
- grep -i skipped capture-$$.log || true
- fi
- rm -f capture-$$.log
-# exit code is not 0, so output log and exit
-else
- cat capture-$$.log
- exit $e
-fi
diff --git a/tests/tools/tracker.sh b/tests/tools/tracker.sh
deleted file mode 100644
index dbe91b46..00000000
--- a/tests/tools/tracker.sh
+++ /dev/null
@@ -1,34 +0,0 @@
-#
-# Helper functions to start your own Tracker instance. This depends
-# on you having your own D-Bus session bus started (first).
-#
-#
-# Copyright (C) 2011 Collabora Ltd. <http://www.collabora.co.uk/>
-#
-# Copying and distribution of this file, with or without modification,
-# are permitted in any medium without royalty provided the copyright
-# notice and this notice are preserved.
-
-tracker_tmpdir=$(mktemp -d)
-
-tracker_init_settings () {
- export XDG_DATA_HOME=$tracker_tmpdir/.local
- export XDG_CACHE_HOME=$tracker_tmpdir/.cache
- export XDG_CONFIG_HOME=$tracker_tmpdir/.config
-}
-
-# This should be called on INT TERM and EXIT
-tracker_cleanup () {
- rm -rf $tracker_tmpdir
- rm -rf $tracker_tmpdir
-}
-
-tracker_start () {
- tracker-control -r > /dev/null 2>&1
-}
-
-tracker_stop () {
- tracker_cleanup
- tracker-control -r > /dev/null 2>&1
-}
-
diff --git a/tests/tools/with-session-bus-eds.sh b/tests/tools/with-session-bus-eds.sh
deleted file mode 100755
index 02f50af2..00000000
--- a/tests/tools/with-session-bus-eds.sh
+++ /dev/null
@@ -1,49 +0,0 @@
-#!/bin/sh
-# with-session-bus-eds.sh - run a program with a temporary D-Bus session daemon
-#
-# interesting bits have been move into dbus to permit reusability
-#
-# Copyright (C) 2007-2008 Collabora Ltd. <http://www.collabora.co.uk/>
-#
-# Copying and distribution of this file, with or without modification,
-# are permitted in any medium without royalty provided the copyright
-# notice and this notice are preserved.
-
-
-cur_dir=`dirname $0`
-
-. $cur_dir"/dbus-session.sh"
-. $cur_dir"/eds.sh"
-
-dbus_parse_args $@
-while test "z$1" != "z--"; do
- shift
-done
-shift
-if test "z$1" = "z"; then dbus_usage; fi
-
-cleanup ()
-{
- eds_stop
- dbus_stop
-}
-
-trap cleanup INT HUP TERM
-
-eds_init_settings
-dbus_init 0
-
-dbus_start
-eds_start
-
-e=0
-
-FOLKS_TESTS_SANDBOXED_DBUS=eds
-export FOLKS_TESTS_SANDBOXED_DBUS
-
-$cur_dir"/execute-test.sh" "$@" || e=$?
-
-trap - INT HUP TERM
-cleanup
-
-exit $e
diff --git a/tests/tools/with-session-bus-tracker.sh b/tests/tools/with-session-bus-tracker.sh
deleted file mode 100755
index 11ad9c79..00000000
--- a/tests/tools/with-session-bus-tracker.sh
+++ /dev/null
@@ -1,48 +0,0 @@
-#!/bin/sh
-# with-session-bus.sh - run a program with a temporary D-Bus session daemon
-#
-# interesting bits have been move into dbus to permit reusability
-#
-# Copyright (C) 2007-2008 Collabora Ltd. <http://www.collabora.co.uk/>
-#
-# Copying and distribution of this file, with or without modification,
-# are permitted in any medium without royalty provided the copyright
-# notice and this notice are preserved.
-
-
-cur_dir=`dirname $0`
-
-. $cur_dir"/dbus-session.sh"
-. $cur_dir"/tracker.sh"
-
-dbus_parse_args $@
-while test "z$1" != "z--"; do
- shift
-done
-shift
-if test "z$1" = "z"; then dbus_usage; fi
-
-cleanup ()
-{
- tracker_stop
- dbus_stop
-}
-
-trap cleanup INT HUP TERM
-
-tracker_init_settings
-dbus_init 0
-
-dbus_start
-tracker_start
-
-FOLKS_TESTS_SANDBOXED_DBUS=tracker
-export FOLKS_TESTS_SANDBOXED_DBUS
-
-e=0
-$cur_dir"/execute-test.sh" "$@" || e=$?
-
-trap - INT HUP TERM
-cleanup
-
-exit $e
diff --git a/tests/tools/with-session-bus.sh b/tests/tools/with-session-bus.sh
deleted file mode 100755
index d8f8d9b4..00000000
--- a/tests/tools/with-session-bus.sh
+++ /dev/null
@@ -1,42 +0,0 @@
-#!/bin/sh
-# with-session-bus.sh - run a program with a temporary D-Bus session daemon
-#
-# interesting bits have been move into dbus to permit reusability
-#
-# Copyright (C) 2007-2008 Collabora Ltd. <http://www.collabora.co.uk/>
-#
-# Copying and distribution of this file, with or without modification,
-# are permitted in any medium without royalty provided the copyright
-# notice and this notice are preserved.
-
-
-cur_dir=`dirname $0`
-
-. $cur_dir"/dbus-session.sh"
-
-dbus_parse_args $@
-while test "z$1" != "z--"; do
- shift
-done
-shift
-if test "z$1" = "z"; then dbus_usage; fi
-
-cleanup ()
-{
- dbus_stop
-}
-
-trap cleanup INT HUP TERM
-
-dbus_init 0
-dbus_start
-
-FOLKS_TESTS_SANDBOXED_DBUS=no-services
-export FOLKS_TESTS_SANDBOXED_DBUS
-
-$cur_dir"/execute-test.sh" "$@" || e=$?
-
-trap - INT HUP TERM
-cleanup
-
-exit $e
diff --git a/tests/tracker/Makefile.am b/tests/tracker/Makefile.am
index 0882260e..c8d481f7 100644
--- a/tests/tracker/Makefile.am
+++ b/tests/tracker/Makefile.am
@@ -36,8 +36,6 @@ LDADD = \
-L$(top_srcdir)/backends/tracker/lib \
$(NULL)
-RUN_WITH_PRIVATE_BUS = $(top_srcdir)/tests/tools/with-session-bus-tracker.sh
-
# in order from least to most complex
noinst_PROGRAMS = \
individual-retrieval \
@@ -100,10 +98,6 @@ noinst_PROGRAMS = \
set-null-avatar \
$(NULL)
-TESTS_ENVIRONMENT = \
- $(RUN_WITH_PRIVATE_BUS) \
- --session \
- --
TESTS = $(noinst_PROGRAMS)
individual_retrieval_SOURCES = \
@@ -338,11 +332,6 @@ set_null_avatar_SOURCES = \
set-null-avatar.vala \
$(NULL)
-CLEANFILES = \
- *.pid \
- *.address \
- $(NULL)
-
-include $(top_srcdir)/git.mk
-include $(top_srcdir)/check.mk
-include $(top_srcdir)/valgrind.mk