Precisely define the detections you would like Chirpity to report on
Search only for a specific species
-
Create new translations for birds' common names or update the common name used with your preferred name for the species.
-
N.B.The common names you supply in a custom list will be adopted for all lists. If you wish to revert to the original common names
- you can do this by either updating the custom list, or by first selecting another list type, then changing the Language settings away from then back
- to your preferred locale
@@ -74,6 +70,12 @@
Language
Choose the language for the "common name" labels, where translations exist. The translated labels have been obtained from eBird.
+
+
If you wish to apply a new translation, or modify a bird's name you can use a custom list. The will be read from the custom list file and names updated if you select "Custom" from the Language dropdown.
+ N.B. You cannot change the call type label, this should remain one of (call), (flight call) or (song).
+
+
diff --git a/js/ui.js b/js/ui.js
index 02ea71a4..91e917fd 100644
--- a/js/ui.js
+++ b/js/ui.js
@@ -4130,9 +4130,18 @@ DOM.gain.addEventListener('input', () => {
break;
}
case 'locale': {
+ let labelFile;
+ if (element.value === 'custom'){
+ labelFile = config.customListFile[config.model];
+ if (! labelFile) {
+ generateToast({message: 'You must select a label file in the list settings to use the custom language option.'});
+ return;
+ }
+ } else {
+ const chirpity = element.value === 'en_uk' && config.model !== 'birdnet' ? 'chirpity' : '';
+ labelFile = `labels/V2.4/BirdNET_GLOBAL_6K_V2.4_${chirpity}Labels_${element.value}.txt`;
+ }
config[config.model].locale = element.value;
- const chirpity = config[config.model].locale === 'en_uk' && config.model !== 'birdnet' ? 'chirpity' : '';
- const labelFile = `labels/V2.4/BirdNET_GLOBAL_6K_V2.4_${chirpity}Labels_${config[config.model].locale}.txt`;
readLabels(labelFile, 'locale');
break;
}
diff --git a/js/worker.js b/js/worker.js
index 667379b9..86f8305b 100644
--- a/js/worker.js
+++ b/js/worker.js
@@ -19,7 +19,7 @@ let NUM_WORKERS;
let workerInstance = 0;
let TEMP, appPath, CACHE_LOCATION, BATCH_SIZE, LABELS, BACKEND, batchChunksToSend = {};
let LIST_WORKER;
-const DEBUG = false;
+const DEBUG = true;
const DATASET = false;
const adding_chirpity_additions = false;
@@ -2957,37 +2957,41 @@ const prepSummaryStatement = (included) => {
await memoryDB.runAsync('BEGIN');
if (STATE.model === 'birdnet'){
for (let i = 0; i < labels.length; i++){
- const id = i;
const [sname, cname] = labels[i].trim().split('_');
- await diskDB.runAsync('UPDATE species SET cname = ? WHERE sname = ? AND id = ?', cname, sname, id);
- await memoryDB.runAsync('UPDATE species SET cname = ? WHERE sname = ? AND id = ?', cname, sname, id);
+ await diskDB.runAsync('UPDATE species SET cname = ? WHERE sname = ?', cname, sname);
+ await memoryDB.runAsync('UPDATE species SET cname = ? WHERE sname = ?', cname, sname);
}
} else {
for (let i = 0; i < labels.length; i++) {
const [sname, newCname] = labels[i].split('_');
// For chirpity, we check if the existing cname ends with a in brackets
- const existingCnameResult = await memoryDB.allAsync('SELECT id, cname FROM species WHERE sname = ?', sname);
+ const existingCnameResult = await memoryDB.allAsync('SELECT cname FROM species WHERE sname = ?', sname);
if (existingCnameResult.length) {
for (let i = 0; i < existingCnameResult.length; i++){
- const {id, cname} = existingCnameResult[i];
+ const {cname} = existingCnameResult[i];
const existingCname = cname;
const existingCnameMatch = existingCname.match(/\(([^)]+)\)$/); // Regex to match word(s) within brackets at the end of the string
const newCnameMatch = newCname.match(/\(([^)]+)\)$/);
// Do we have a spcific call type to match?
if (newCnameMatch){
// then only update the database where existing and new call types match
- if (newCnameMatch[1] === existingCnameMatch[1]){
- await diskDB.runAsync('UPDATE species SET cname = ? WHERE sname = ? AND id = ?', newCname, sname, id);
- await memoryDB.runAsync('UPDATE species SET cname = ? WHERE sname = ? AND id = ?', newCname, sname, id);
+ if (newCnameMatch[0] === existingCnameMatch[0]){
+ const callTypeMatch = '%' + newCnameMatch[0] + '%' ;
+ await diskDB.runAsync("UPDATE species SET cname = ? WHERE sname = ? AND cname LIKE ?", newCname, sname, callTypeMatch);
+ await memoryDB.runAsync("UPDATE species SET cname = ? WHERE sname = ? AND cname LIKE ?", newCname, sname, callTypeMatch);
}
} else { // No () in the new label - so we add the new name to all the species call types in the database
- let appendedCname = newCname;
+ let appendedCname = newCname, bracketedWord;
if (existingCnameMatch) {
- const bracketedWord = existingCnameMatch[1];
- appendedCname += ` (${bracketedWord})`; // Append the bracketed word to the new cname (for each of the existingCnameResults)
+ bracketedWord = existingCnameMatch[0];
+ appendedCname += ` ${bracketedWord}`; // Append the bracketed word to the new cname (for each of the existingCnameResults)
+ const callTypeMatch = '%' + bracketedWord + '%';
+ await diskDB.runAsync("UPDATE species SET cname = ? WHERE sname = ? AND cname LIKE ?", appendedCname, sname, callTypeMatch);
+ await memoryDB.runAsync("UPDATE species SET cname = ? WHERE sname = ? AND cname LIKE ?", appendedCname, sname, callTypeMatch);
+ } else {
+ await diskDB.runAsync("UPDATE species SET cname = ? WHERE sname = ?", appendedCname, sname);
+ await memoryDB.runAsync("UPDATE species SET cname = ? WHERE sname = ?", appendedCname, sname);
}
- await diskDB.runAsync('UPDATE species SET cname = ? WHERE sname = ? AND id = ?', appendedCname, sname, id);
- await memoryDB.runAsync('UPDATE species SET cname = ? WHERE sname = ? AND id = ?', appendedCname, sname, id);
}
}
}